我想将一个表的行插入另一个表中。为此,我有以下程序。
ALTER PROCEDURE LOADDATA_a
AS
BEGIN
TRUNCATE TABLE STIDENT_A
DECLARE @SID INT
DECLARE @SNAME VARCHAR(50)
DECLARE @SUB VARCHAR(50)
DECLARE @MARKS INT
DECLARE LOAD_DATA CURSOR FAST_FORWARD FOR
SELECT SID,SNAME,SUB,MARKS
FROM student
OPEN LOAD_DATA
FETCH NEXT FROM LOAD_DATA INTO @SID,@SNAME,@SUB,@MARKS
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRANSACTION
INSERT INTO STIDENT_A(SID,SNAME,SUB,MARKS) VALUES (@SID,@SNAME,@SUB,@MARKS)
IF @@ERROR != 0
BEGIN
ROLLBACK TRANSACTION
RETURN
END
ELSE
BEGIN
COMMIT TRANSACTION
END
FETCH NEXT FROM LOAD_DATA INTO @SID,@SNAME,@SUB,@MARKS
END
CLOSE LOAD_DATA
DEALLOCATE LOAD_DATA
END
每当一行无法插入时,光标会失败并停在那里,但我需要它继续。怎么做?
答案 0 :(得分:4)
显然,您在RETURN
之后立即收到ROLLBACK TRANSACTION
声明。你试过删除吗?
虽然您也可以使用TRY/CATCH
改写身体,但是这样:
...
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
INSERT INTO STIDENT_A(SID,SNAME,SUB,MARKS)
VALUES (@SID,@SNAME,@SUB,@MARKS);
END TRY
BEGIN CATCH
-- this section must have some statement,
-- so, why not log the erroneous data to the screen at least?
PRINT @SID;
PRINT @SNAME;
PRINT @SUB;
PRINT @MARKS;
PRINT ''; -- an empty line as a delimiter
-- or, perhaps, into a table?
--INSERT INTO SomeFailLog (SID,SNAME,SUB,MARKS)
--VALUES (@SID,@SNAME,@SUB,@MARKS);
END CATCH;
FETCH NEXT FROM LOAD_DATA INTO @SID,@SNAME,@SUB,@MARKS;
END;
...
但是如果您知道具体可能导致插入失败的原因,那么最好只提出一个只生成有效数据的语句来插入。
例如,如果问题是student
中的某些SID已经存在于STIDENT_A
中而您需要省略它们,则只需尝试以下而不是您的过程:
INSERT INTO STIDENT_A (SID, SNAME, SUB, MARKS)
SELECT s.SID, s.SNAME, s.SUB, s.MARKS
FROM student AS s
LEFT JOIN STIDENT_A AS a ON s.SID = a.SID
WHERE a.SID IS NULL
;
如果您在传输数据时指定了可能存在的问题,我们可能会帮助您找到专门针对此问题的最有效解决方案。
更新 处理评论
如果问题是SNAME
中STIDENT_A
的最大长度小于student
中同名列的最大长度,而某些值可能不合适,则可以使用过滤(WHERE
子句)以将插入的行限制为实际长度SNAME
不超过某个值的行:
INSERT INTO STIDENT_A (SID, SNAME, SUB, MARKS)
SELECT SID, SNAME, SUB, MARKS
WHERE LEN(SNAME) <= @maxlength
;
您可以查询元数据以确定所需列的最大长度。有多种方法,一种是使用sys.columns
系统目录:
DECLARE @maxlength int;
SELECT @maxlength = max_length
FROM sys.columns
WHERE object_id = OBJECT_ID('STIDENT_A')
AND name = 'SNAME'
;
确定无法插入哪些行:
INSERT INTO STIDENT_A (SID, SNAME, SUB, MARKS)
SELECT SID, SNAME, SUB, MARKS
WHERE LEN(SNAME) > @maxlength
;
答案 1 :(得分:2)
试试这个: -
DECLARE @intFlag INT
SET @intFlag = 0
WHILE (@intFlag <=5)
BEGIN
begin Try
if @intFlag = 3
begin
SET @intFlag = @intFlag + 'A'
End
Else
begin
PRINT @intFlag
end
End Try
Begin Catch
--print 'Error'
-- continue
End catch
SET @intFlag = @intFlag + 1
END
GO