我写了一个存储过程,有时我需要连续多次调用。 sp使用一个游标。这是我第一次意识到为什么罗伯特·维埃拉写道"游标很慢"在我多年前读过的SS2000 Pro书中。
你能建议更好的实施吗? 我很抱歉使用复制和粘贴而不是使用简化版本,无论如何一般建议都很好我也不希望你重写它。
这里是代码:
CREATE PROC sp_DuplicaDocDistrib(@ID_DIP_SRC INT ,@ID_DIP_DEST int) AS
BEGIN
DECLARE @ID_LISTA INT
DECLARE @ID_DISTRIB INT
DECLARE @TIPO_DISTRIB NVARCHAR(1)
DECLARE @NRO_COPIE NVARCHAR(50)
DECLARE @NOTE NVARCHAR(50)
SET @ID_LISTA = (SELECT LAST_ID FROM SW9_SEQUENCES WHERE SEQ_NAME ='DOCN_ID_LISTA_DISTRIBUZIONE')
SET @NOTE = 'Automatically distributed on '+ convert(varchar(25), getdate(), 103)
DECLARE CURSOR_DOCDISTRIB CURSOR FOR
SELECT ID_DISTRIBUZIONE,TIPO_DISTRIBUZIONE,NRO_COPIE from DOC_LISTE_DISTRIBUZIONE BASE
WHERE BASE.ID_DIPENDENTE = @ID_DIP_SRC
AND NOT EXISTS ( SELECT ID_LISTA FROM DOC_LISTE_DISTRIBUZIONE
WHERE ID_DISTRIBUZIONE = BASE.ID_DISTRIBUZIONE AND ID_DIPENDENTE = @ID_DIP_DEST)
OPEN CURSOR_DOCDISTRIB
FETCH NEXT FROM CURSOR_DOCDISTRIB INTO @ID_DISTRIB,@TIPO_DISTRIB,@NRO_COPIE
WHILE @@FETCH_STATUS = 0
BEGIN
SET @ID_LISTA = @ID_LISTA +1
PRINT @ID_LISTA
PRINT @ID_DISTRIB
INSERT INTO DOC_LISTE_DISTRIBUZIONE (ID_LISTA,ID_DISTRIBUZIONE,ID_DIPENDENTE,NRO_COPIE,TIPO_DISTRIBUZIONE,NOTE)
VALUES (@ID_LISTA,@ID_DISTRIB,@ID_DIP_DEST,@NRO_COPIE,@TIPO_DISTRIB,@NOTE)
FETCH NEXT FROM CURSOR_DOCDISTRIB INTO @ID_DISTRIB,@TIPO_DISTRIB,@NRO_COPIE
END
CLOSE CURSOR_DOCDISTRIB
DEALLOCATE CURSOR_DOCDISTRIB
UPDATE SW9_SEQUENCES
SET LAST_ID = @ID_LISTA
WHERE SEQ_NAME = 'DOCN_ID_LISTA_DISTRIBUZIONE'
END
答案 0 :(得分:2)
似乎你可以在这里避开光标
请将光标替换为如下所示的声明。我没有把所有列放在这里,但确定你明白了!
INSERT INTO DOC_LISTE_DISTRIBUZIONE (ID_LISTA,ID_DISTRIBUZIONE,ID_DIPENDENTE,NRO_COPIE,TIPO_DISTRIBUZIONE,NOTE)
SELECT @ID_LISTA,ID_DISTRIBUZIONE, @ID_DIP_DEST, TIPO_DISTRIBUZIONE,NRO_COPIE
From DOC_LISTE_DISTRIBUZIONE BASE
WHERE BASE.ID_DIPENDENTE = @ID_DIP_SRC
AND NOT EXISTS ( SELECT ID_LISTA FROM DOC_LISTE_DISTRIBUZIONE
WHERE ID_DISTRIBUZIONE = BASE.ID_DISTRIBUZIONE AND ID_DIPENDENTE = @ID_DIP_DEST
详细了解Insert Data From One Table to Another Table
如果您需要增量字段,则可以使用ROW_NUMBER()
来实现此目的。
即
Select ROW_NUMBER() Over (order By FieldName1) IncrementField ,FieldName2
From TableName
答案 1 :(得分:1)
使用FAST_FORWARD游标(它是static,forward_only,read-only的简写),它们比默认游标快得多。
但是,我相信你根本不需要光标,它可以重写为简单的INSERT .. SELECT FROM。
答案 2 :(得分:1)
ID_LISTA
似乎不是IDENTITY列,这意味着您需要手动填充此列。
您将光标声明为:
SELECT ID_DISTRIBUZIONE,TIPO_DISTRIBUZIONE,NRO_COPIE from DOC_LISTE_DISTRIBUZIONE BASE
WHERE BASE.ID_DIPENDENTE = @ID_DIP_SRC
AND NOT EXISTS (
SELECT ID_LISTA FROM DOC_LISTE_DISTRIBUZIONE
WHERE ID_DISTRIBUZIONE = BASE.ID_DISTRIBUZIONE AND ID_DIPENDENTE = @ID_DIP_DEST
)
但是,当您遍历光标时,您似乎正在进行的唯一处理是增加@ID_LISTA
的值。因此,一种解决方案可能是开始创建临时表:
CREATE TABLE #Temp (
ID_LISTA_INC int IDENTITY(1,1),
ID_DISTRIBUZIONE ...,
ID_DIPENDENTE ...
(etc)
)
然后,
INSERT INTO #Temp
(ID_DISTRIBUZIONE, ID_DIPENDENTE, ...)
SELECT ID_DISTRIBUZIONE,TIPO_DISTRIBUZIONE,NRO_COPIE from DOC_LISTE_DISTRIBUZIONE BASE
WHERE BASE.ID_DIPENDENTE = @ID_DIP_SRC
AND NOT EXISTS (
SELECT ID_LISTA FROM DOC_LISTE_DISTRIBUZIONE
WHERE ID_DISTRIBUZIONE = BASE.ID_DISTRIBUZIONE AND ID_DIPENDENTE = @ID_DIP_DEST
)
使用您插入#Temp
的数据填充DOC_LISTE_DISTRIBUZIONE
。然后你应该能够做到:
INSERT INTO DOC_LISTE_DISTRIBUZIONE
(ID_LISTA,ID_DISTRIBUZIONE,ID_DIPENDENTE,NRO_COPIE,TIPO_DISTRIBUZIONE,NOTE)
SELECT ID_LISTA_INC + @ID_LISTA, ID_DISTRIBUZIONE,ID_DIPENDENTE, ... FROM #Temp
SELECT @ID_LISTA = @ID_LISTA + max(ID_LISTA_INC) FROM #Temp
UPDATE SW9_SEQUENCES
SET LAST_ID = @ID_LISTA
WHERE SEQ_NAME = 'DOCN_ID_LISTA_DISTRIBUZIONE'