1

Excel からレコードをインポートしていますが、重複を避けたいと考えています。ASP Classic では、データベースの重複をチェックする関数を作成しました。見つかった場合は、ユーザー名の末尾に番号を追加し、ユーザー名が一意かどうかを再度確認します。たとえば、petejones は petejones1 になります。残念ながら、データベースには約 15 万件のレコードがあり、一意性を検索するのに非常に時間がかかるため、このスクリプトは非常に低速です。T-SQL の SQL Server 2008 で直接同じことを行う方法はありますか? そのため、プロセス全体が非常に迅速になります。一意にするプロセスはありますか?

これが従来の 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を学んでいるので、どんな支援も大歓迎です。

4

3 に答える 3

3

これは SQL で行うことができます。これは一致する名前を探します。一致が見つかった場合は、現在追加されている最大数を取得し、1 を追加します。したがって、せいぜい 2 つのSELECTSを実行します。重複が多い場合は高速になるはずです。

-- 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 
于 2012-05-04T13:52:07.437 に答える
1

この面倒な式は、最初に使用可能なユーザー名を取得します。同じ名前のユーザーがいて、残りのユーザー名が数字の場合、expression は次の数字と連結されたユーザー名を返します。そのようなユーザー名が見つからない場合、expression はこのユーザー名を返します。

各 '@username' を実際の値に置き換えるか、より適切には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 のテスト グラウンドがあります。set @username = 'aa'結果を表示するには、他のユーザー名に置き換えてください。

于 2012-05-04T13:52:57.817 に答える
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部分は、どの重複ユーザー名を行 1 にするか、行 2 にするかなどを決定します。

次は、この行番号をユーザー名と組み合わせる問題です。

UserName + CONVERT(VARCHAR, RowNumber) [UniqueName]

これにより、Username0、Username1、username2...が生成されるため、次のステップは、「username0」をユーザー名としてのみ表示し、Username、username1、username2 のリストを提供することです。

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

これは基本的に、行番号が 0 の場合は null になり、この結果が null の場合は '' になることを示しています。

于 2012-05-04T14:03:33.983 に答える