2012-05-04 8 views
1

Excelからレコードをインポートしていますが、重複を避けたいと思います。 ASPクラシックでは、データベースの重複をチェックする関数を書いています。見つかった場合は、ユーザー名の末尾に数字を追加し、ユーザー名が一意であるかどうかを再度確認します。たとえば、petejonesはpetejones1になります。残念なことに、このスクリプトはデータベースが約150kレコードになるほど遅くなり、一意性を検索するのに永遠にかかります。 T-SQLのSQL Server 2008で直接同じことを行う方法はありますか?プロセス全体が迅速に邪悪になるでしょう。ユニークなプロセスがありますか?重複するSQL Server 2008と従来のASPの防止

これは古典的なASPの機能です。私はこれを行うためのより良い方法があることを知っていますので、私のスクリプトを笑ってはいけません。

FUNCTION CreateUniqueUsername(str) 
    SET DbConn = Server.CreateObject("ADODB.connection") 
    DbConn.Open DSN_LINK 
    nCounter = 0 
    Unique = "" 
    IF InStr(str, "@") > 0 THEN 
    strUsername = Left(str,InStr(str, "@")-1) 
    ELSE 
    strUsername = str 
    END IF 
    strUsername = FormatUsername(strUsername) 
    strSQL = "SELECT UserName FROM Member WHERE UserName = '" & strUsername & "';" 
    SET rs = DbConn.Execute(strSQL) 
    IF rs.EOF AND rs.BOF THEN 
    nFinalUsername = strUsername 
    ELSE 
    DO UNTIL Unique = true 
     nCounter = nCounter + 1 
     nFinalUsername = strUsername & nCounter 
     strSQL2 = "SELECT UserName FROM Member WHERE UserName = '" & nFinalUsername & " ' " 
     SET objRS = DbConn.Execute(strSQL2) 
     IF objRS.EOF THEN 
     Unique = true 
     ELSE 
     intCount = intCount 
     END IF 
    LOOP 
    objRS.Close 
    SET objRS = Nothing 
    END IF 
    rs.Close 
    SET rs = Nothing 
    SET DbConn = Nothing 
    CreateUniqueUsername = nFinalUsername 
END FUNCTION 

FUNCTION FormatUsername(str) 
    Dim OutStr 
    IF ISNULL(str) THEN EXIT FUNCTION 
    OutStr = lCase(Trim(str)) 
    OutStr = Replace(OutStr, "’", "") 
    OutStr = Replace(OutStr, "”", "") 
    OutStr = Replace(OutStr, "'","") 
    OutStr = Replace(OutStr, "&","and") 
    OutStr = Replace(OutStr, "'", "") 
    OutStr = Replace(OutStr, "*", "") 
    OutStr = Replace(OutStr, ".", "") 
    OutStr = Replace(OutStr, ",", "") 
    OutStr = Replace(OutStr, CHR(34),"") 
    OutStr = Replace(OutStr, " ","") 
    OutStr = Replace(OutStr, "|","") 
    OutStr = Replace(OutStr, "&","") 
    OutStr = Replace(OutStr, "[","") 
    OutStr = Replace(OutStr, ";", "") 
    OutStr = Replace(OutStr, "]","") 
    OutStr = Replace(OutStr, "(","") 
    OutStr = Replace(OutStr, ")","") 
    OutStr = Replace(OutStr, "{","") 
    OutStr = Replace(OutStr, "}","") 
    OutStr = Replace(OutStr, ":","") 
    OutStr = Replace(OutStr, "/","") 
    OutStr = Replace(OutStr, "\","") 
    OutStr = Replace(OutStr, "?","") 
    OutStr = Replace(OutStr, "@","") 
    OutStr = Replace(OutStr, "!","") 
    OutStr = Replace(OutStr, "_","") 
    OutStr = Replace(OutStr, "''","") 
    OutStr = Replace(OutStr, "%","") 
    OutStr = Replace(OutStr, "#","") 
    FormatUsername = OutStr 
END FUNCTION 

私はまだSQLを勉強しています。

答えて

3

これはSQLで行うことができます。 これは、一致する名前を探します。一致するものが見つかった場合は、現在追加されている最大数が取得され、追加されます。したがって、多くても2つです選択肢です。重複が多い場合は速くする必要があります。

-- example table 
declare @Member table(ID int identity, UserName varchar(80)) 
insert @Member values('Pete') 
insert @Member values('Jill') 
insert @Member values('Bob') 
insert @Member values('Sam') 
insert @Member values('Pete1') 
insert @Member values('Pete2') 
insert @Member values('Pete3') 
insert @Member values('Bob1') 


declare @UserName varchar(80), @FinalUserName varchar(80) 
set @UserName = 'Pete' 

set @FinalUserName = @UserName 
if(exists(SELECT 1 FROM @Member WHERE left(UserName,len(@UserName)) = @UserName)) 
begin 
    SELECT 
     @FinalUserName = @UserName + convert(varchar(12),max(substring(UserName,len(@UserName)+1,99)+1)) 
    FROM @Member 
    WHERE left(UserName,len(@UserName)) = @UserName 
end 

SELECT @FinalUserName 
+0

いくつかの説明は必須ですが、投稿コードは答えがありません。ユーザーが自分の要求したユーザー名の末尾に数字を追加した場合、あなたのコードはすべての場合に機能しますか? – AnthonyWJones

+0

名前に名前が付いている場合(例:Pete500)、「Pete500」が存在する場合は「Pete5001」に変更されます。次の「ピート」は「Pete5002」になります。これは潜在的な欠点です。 – jim31415

+0

+1ユーザー名が一意である限り、問題はありません。 – AnthonyWJones

1

この厄介な表現は、最初に利用可能なユーザー名を取得します。同じ名前のユーザがあり、残りのユーザの名前が数字の場合、式は次の数字で連結されたユーザ名を返します。そのようなユーザー名が見つからない場合、式はこのユーザー名を返します。

各 '@ユーザー名'を実際の値に置き換えるか、SqlCommand.ExecuteScalarを使用することをおすすめします。 SqlCommandはパラメータの使用を許可します。これは、醜い文字列を連結する必要がなく、Sql Injectionの使用を妨げるため、より良い解決策です。

select @username 
    + isnull(convert (varchar (10), 
     max (case when isnumeric (substring (m.Username, len (@username) + 1, 100)) = 1 
        then cast (substring (m.Username, len (@username) + 1, 100) as int) 
        else (case when m.username = @username then 0 end) 
        end) 
     + 1), '') UserName 
from @members m 
where m.username like @username + '%' 

ここにはSql Fiddle testing groundがあります。結果を見るにはset @username = 'aa'を他のユーザー名に置き換えてください。

0

これは、重複を許可するステージングテーブルに挿入し、ステージングテーブルからメインテーブルに転送して、プロセス内の重複を解決することで実現できます。

INSERT INTO MainTable (Column1, Column2, UniqueName) 
SELECT Column1, 
     Column2, 
     UserName + ISNULL(CONVERT(VARCHAR, NULLIF(RowNumber, 0)), '') [UniqueName] 
FROM ( SELECT *, *, ROW_NUMBER() OVER (PARTITION BY UserName ORDER BY Column1) - 1 [Rownumber] 
      FROM StagingTable 
     ) staging 

このステートメントの重要な部分である:

ROW_NUMBER() OVER (PARTITION BY UserName ORDER BY Column1) - 1 

これは各行に行番号(明らかに)を与えます。 PARTITION BYはグループのように動作しますが、これは基本的にユーザー名が変更されると行数が1にリセットされることを意味します。 ORDER BY部分は行2などの行1になる重複ユーザー名を決定します。ROW_NUMBER()は1から始まるので、1からそれを差し引いて0から始まります。

次へユーザ名と行番号:

UserName + CONVERT(VARCHAR, RowNumber) [UniqueName] 

これはので、次のステップは、「username0は」のみユーザー名のリストを与えるために、ユーザ名として表示されるようUSERNAME1、USERNAME2することです... USERNAME2 username0、USERNAME1をもたらすであろう:

UserName + ISNULL(CONVERT(VARCHAR, NULLIF(RowNumber, 0)), '') [UniqueName] 

これは基本的にif rownumberは0で、次にnullになり、結果がnullの場合は ''になります。

関連する問題