存储过程算法需要9个小时 - 更好的方法吗?

Loc*_*ock 2 sql sql-server plsql stored-procedures

我需要构建一个SQL存储过程,它基本上使用ID更新现有的表(大约150,000行).

此存储过程将运行的表基本上是人员列表,他们的名字,地址等.

现在该人的id的算法如下: - 取得人名的前4个字符. - 接受姓氏的前2个字符. - 用0表示填充其余部分,最后用计数编号,直到该字段为8个字符.

例如,名称JOHN SMITH的ID为"JOHNSM00".如果有2个JOHN SMITH,那么下一个人的ID就是JOHNSM01.例如,如果人名是FI LYNN,则ID将为FILY0000.

我已经编写了以下存储过程,但运行大约需要9个小时!有没有更好的办法让我失踪?

ALTER PROCEDURE [dbo].[LM_SP_UPDATE_PERSON_CODES]
AS

DECLARE @NAMEKEY NVARCHAR(10)
DECLARE @NEWNAMEKEY NVARCHAR(10)
DECLARE @LENGTH INT
DECLARE @KEYCOUNT INT
DECLARE @I INT
DECLARE @PADDING NVARCHAR(8)
DECLARE @PERSONS CURSOR
DECLARE @FIRSTNAME NVARCHAR(30)
DECLARE @LASTNAME NVARCHAR(30)

SET @PADDING = '00000000'
--FIRST CLEAR OLD NEW NAMEKEYS IF ANY EXIST
UPDATE LM_T_PERSONS SET NEW_NAMEKEY = NULL
SET @PERSONS = CURSOR FOR
SELECT NAMEKEY, NAME_2, NAME_1 FROM LM_T_PERSONS

OPEN @PERSONS
FETCH NEXT FROM @PERSONS INTO @NAMEKEY, @FIRSTNAME, @LASTNAME

WHILE @@FETCH_STATUS = 0
BEGIN
    --CHECK THE LENGTH OF FIRST NAME TO MAKE SURE NOTHING EXCEEDS 4
    SET @LENGTH = LEN(@FIRSTNAME)
    IF @LENGTH > 4 
        SET @LENGTH = 4

    SET @NEWNAMEKEY = SUBSTRING(@FIRSTNAME,1,@LENGTH)

    --CHECK THE LENGTH OF LAST NAME TO MAKE SURE NOTHING EXCEEDS 2
    SET @LENGTH = LEN(@LASTNAME)
    IF @LENGTH > 2
        SET @LENGTH = 2

    SET @NEWNAMEKEY = @NEWNAMEKEY + SUBSTRING(@LASTNAME,1,@LENGTH)
    SET @LENGTH = LEN(@NEWNAMEKEY)
    SET @I = 0
    SET @PADDING = SUBSTRING('00000000',1,8 - LEN(@NEWNAMEKEY) - LEN(CONVERT(NVARCHAR(8),@I)))
    --SEE IF THIS KEY ALREADY EXISTS
    SET @KEYCOUNT = (SELECT COUNT(1) FROM LM_T_PERSONS WHERE NEW_NAMEKEY = @NEWNAMEKEY + @PADDING + CONVERT(NVARCHAR(8),@I) )
    WHILE @KEYCOUNT > 0
    BEGIN
        SET @I = @I+1
        SET @PADDING = SUBSTRING('00000000',1,8 - LEN(@NEWNAMEKEY) - LEN(CONVERT(NVARCHAR(8),@I)))
        SET @KEYCOUNT = (SELECT COUNT(1) FROM LM_T_PERSONS WHERE NEW_NAMEKEY = @NEWNAMEKEY + @PADDING + CONVERT(NVARCHAR(8),@I) )
    END
    UPDATE LM_T_PERSONS SET NEW_NAMEKEY = @NEWNAMEKEY + @PADDING + CONVERT(NVARCHAR(8),@I) WHERE NAMEKEY = @NAMEKEY

    FETCH NEXT FROM @PERSONS INTO @NAMEKEY, @FIRSTNAME, @LASTNAME
END
CLOSE @PERSONS
DEALLOCATE @PERSONS
Run Code Online (Sandbox Code Playgroud)

Gle*_*hes 6

这样的东西可以在没有光标的情况下完成:

UPDATE P
SET NAMEKEY = FIRSTNAME + LASTNAME + REPLICATE('0', 8 - LEN(FIRSTNAME) - LEN(LASTNAME) - LEN(I)) + I
FROM
  LM_T_PERSONS AS P JOIN
  (
    SELECT
      NAMEKEY,
      LEFT(NAME_2, 4) AS FIRSTNAME,
      LEFT(NAME_1, 2) AS LASTNAME,
      CONVERT(NVARCHAR, ROW_NUMBER() OVER(PARTITION BY LEFT(NAME_2, 4), LEFT(NAME_1, 2) ORDER BY NAMEKEY)) AS I
    FROM
      LM_T_PERSONS
  ) AS DATA
  ON P.NAMEKEY = DATA.NAMEKEY
Run Code Online (Sandbox Code Playgroud)

您可以在此处验证查询:http: //sqlfiddle.com/#!3/47365/19