SQL Server:游标更新问题

时间:2018-05-10 15:18:10

标签: sql-server tsql

我有一个自定义函数来分割字符串:

 CREATE FUNCTION [dbo].[SplitString] 
 (
     @str NVARCHAR(MAX), 
     @separator CHAR(1)
 )
 RETURNS TABLE 
 AS
 return (
 with tokens(p, a, b) AS (
     select 
         cast(1 as bigint), 
         cast(1 as bigint), 
         charindex(@separator, @str)
     union all
     select
         p + 1, 
         b + 1, 
         charindex(@separator, @str, b + 1)
     from tokens
     where b > 0
 )
 select
     p-1 ItemIndex,
     substring(
         @str, 
         a, 
         case when b > 0 then b-a ELSE LEN(@str) end) 
     AS Item
 from tokens
 );

(该代码归功于Stack Overflow上的其他人,我不记得了)

这在我用来做同样事情的另一个脚本中工作正常。

最终,这构成了ETL的一部分,目的是实现这一目标:

ID | Title
1  | Mrs K

进入这个:

ClientContactRef | Title | Forename
1                | Mrs   | K

我的代码如下所示:

DECLARE @Title varchar(max)
DECLARE @ThirdPartyRef int

DECLARE cur CURSOR FOR
SELECT Title, ID FROM [Abacus].[dbo].[ThirdParty]
WHERE Title IS NOT NULL

OPEN cur

WHILE @@FETCH_STATUS = 0
    BEGIN
FETCH NEXT FROM cur INTO @Title, @ThirdPartyRef

UPDATE Migrate.ClientContact
SET Title = LEFT(Item,60)
FROM SplitString(@Title,CHAR(32))
WHERE ItemIndex = 0
AND Migrate.ClientContact.ClientContactRef = @ThirdPartyRef

UPDATE Migrate.ClientContact
SET Forename = LEFT(Item,60)
FROM SplitString(@Title,CHAR(32))
WHERE ItemIndex = 1
AND Migrate.ClientContact.ClientContactRef = @ThirdPartyRef

END

CLOSE Cur
Deallocate Cur

GO

如上所述,我在其他地方使用它将地址拆分为5个组件(我也需要在这里做)但我得到了同样的问题 - 即在游标内部似乎没有任何输出,所以我的所有目标字段都以null结尾。

splitstring函数按照预期在单行上的光标外工作,但是一旦在光标内部,似乎没有返回任何内容。我试图在游标中放置一个临时表以捕获splitstring的输出,并且没有任何。

提前致谢

西蒙

1 个答案:

答案 0 :(得分:1)

这应该在单个更新语句中并且没有光标的情况下实现您要执行的操作。

UPDATE MCC SET 
    MCC.Title = CASE WHEN SST.ItemIndex = 0 THEN LEFT(SST.Item,60) ELSE MCC.Title END
    ,MCC.ForeName = CASE WHEN SST.ItemIndex = 1 THEN LEFT(SST.Item,60) ELSE MCC.ForeName END
FROM Migrate.ClientContact AS MCC
    JOIN Abacus.dbo.ThirdParty AS ATP
        ON MCC.ClientContactRef = ATP.ID
    CROSS APPLY SplitString(ATP.Title,CHAR(32)) AS SST
WHERE SST.ItemIndex IN (0,1)
;