4

我想将一个表的行插入另一个表。为此,我有以下程序。

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

每当插入行失败时,游标就会失败并停在那里,但我需要它继续。怎么做?

4

2 回答 2

5

显然,您在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;
...

但是,如果您知道具体可能导致插入失败的原因,那么提出一个仅生成要插入的有效数据的语句可能会更好。

例如,如果问题是某些 SIDstudent已经存在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
;

如果您在传输数据时指定具体可能出现的问题,我们可能会帮助您找到专门针对该问题的最有效的解决方案。


更新解决评论

如果问题是 in 的最大长度SNAME小于 inSTIDENT_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
;
于 2013-04-09T06:00:35.533 回答
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 
于 2014-02-14T12:53:04.920 回答