2016-09-09 18 views
0

私は、別のテーブルから複数の行を繰り返し処理するカーソルを持っています。SQLカーソルの問題 - NULLを返す。

これは、トリガーにカーソルを追加し、別の表からバルクとして挿入された行を反復処理することによって行われます。

例:atsprojectテーブルにいくつかのプロジェクトが追加されます。これにより、以下のaddトリガーがvatmatrixテーブルに追加されます。

問題は、カーソルが通過してすべての行の値をnullとして追加することです。

さらにこれを診断する方法はありますか?

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER TRIGGER [dbo].[UPDATE_VATMATRIX] ON [dbo].[atsproject] 
FOR UPDATE, INSERT 
AS 

DECLARE @project AS VARCHAR(25) 
DECLARE @client AS VARCHAR(25) 
DECLARE @dim2 AS VARCHAR(25) 
DECLARE @period_from AS INT 
DECLARE @period_to AS INT 
DECLARE @status AS CHAR(1) 
DECLARE @user_id AS VARCHAR(25) 
DECLARE @unit_id AS VARCHAR(25) 

--DECLARE @ROW_NUM VARCHAR (25) 

DECLARE @sequence_no AS INT 

--DECLARE @TrigTempUpdate_Cursor CURSOR 

--FIND MAXIMUM VALUE FOR SEQUENCE NUMBER 
SET @sequence_no = (SELECT MAX(v) FROM (SELECT sequence_no FROM agldefmatdet WHERE matrix_id = 11) AS value(v)); 

DECLARE Tbl_Cursor CURSOR FOR 

SELECT project, 
    client, 
    dim2, 
    period_from, 
    period_to, 
    status, 
    user_id, 
    unit_id 
    FROM inserted 

OPEN Tbl_Cursor; 

FETCH NEXT FROM Tbl_Cursor; 

WHILE @@FETCH_STATUS = 0 


    BEGIN 

    --SELECT TOP 1 * FROM inserted 

    IF EXISTS (SELECT TOP 1 * FROM inserted) AND NOT EXISTS (SELECT TOP 1 * FROM deleted) 

    INSERT INTO [dbo].[agldefmatdet] 
     (att_val_from_1, 
      att_val_from_2, 
      att_val_from_3, 
      att_val_from_4, 
      att_val_to_1, 
      att_val_to_2, 
      att_val_to_3, 
      att_val_to_4, 
      att_value_1, 
      att_value_2, 
      att_value_3, 
      att_value_4, 
      client, 
      dim_value, 
      last_update, 
      matrix_id, 
      period_from, 
      period_to, 
      sequence_no, 
      status, 
      user_id) 
    SELECT @project, 
      '', 
      '', 
      '', 
      @project, 
      '', 
      '', 
      '', 
      @project, 
      '', 
      '', 
      '', 
      @client, 
      @dim2, 
      GETDATE(), 
      '11', 
      '0', 
      '0', 
      @sequence_no + 1, 
      @status, 
      @user_id 
RETURN; 


    IF EXISTS (select * from inserted) AND EXISTS (select * from deleted) 

    UPDATE agldefmatdet 
    SET dim_value = @dim2, 
      last_update = GETDATE(), 
      period_from = @period_from, 
      period_to = @period_to, 
      status = @status, 
      user_id = @user_id 
      WHERE att_val_from_1 = @project AND matrix_id = '11' AND client = 'LU' 


RETURN; 
     FETCH NEXT FROM Tbl_Cursor; 
    END; 
CLOSE Tbl_Cursor; 
DEALLOCATE Tbl_Cursor; 
GO 
+0

これはエラーを発生させませんか?とにかくカーソルが必要なのはなぜですか? –

+0

値が 'NULL'の理由は、' FETCH'文で変数のリストを指定する必要があるためです。トリガーを途中で終了する無関係な 'RETURN'ステートメントなど、他にも多くのエラーがあります。私はこのバージョンを捨てて、カーソルの代わりにセットベースのメソッドを使って書き直すことをお勧めします。これにより、パフォーマンスが向上し、コードがより読みやすくなります。 –

答えて

0

方法を支持またはコードの残りの部分をデバッグしていないが、あなたの当面の問題は、次のステートメントを取得、彼らはあなたがループ内で使用します変数にカーソル宣言で列をマップする必要があります。

FETCH NEXT FROM Tbl_Cursor 
INTO @project,@client,@dim2,@period_from,@period_to,@status,@user_id,@unit_id; 

EDIT:セットベースのソリューションとして

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER TRIGGER [dbo].[UPDATE_VATMATRIX] ON [dbo].[atsproject] 
FOR UPDATE, INSERT 
AS 

DECLARE @sequence_no AS INT 

--DECLARE @TrigTempUpdate_Cursor CURSOR 

--FIND MAXIMUM VALUE FOR A MATRIX 11 SEQUENCE NUMBER 
/* replaced with select below 
SET @sequence_no = (SELECT MAX(v) FROM (SELECT sequence_no FROM agldefmatdet WHERE matrix_id = 11) AS value(v)); 
*/ 

SELECT @sequence_no = max(sequence_no) FROM agldefmatdet WHERE matrix_id = 11; /* NB, hard coding IDs isn't a good idea */ 


    INSERT INTO [dbo].[agldefmatdet] 
     (att_val_from_1, 
      att_val_from_2, 
      att_val_from_3, 
      att_val_from_4, 
      att_val_to_1, 
      att_val_to_2, 
      att_val_to_3, 
      att_val_to_4, 
      att_value_1, 
      att_value_2, 
      att_value_3, 
      att_value_4, 
      client, 
      dim_value, 
      last_update, 
      matrix_id, 
      period_from, 
      period_to, 
      sequence_no, 
      status, 
      user_id) 
    SELECT project, 
      '', 
      '', 
      '', 
      project, 
      '', 
      '', 
      '', 
      project, 
      '', 
      '', 
      '', 
      client, 
      dim2, 
      GETDATE(), 
      '11', 
      '0', 
      '0', 
      @sequence_no + row_number() over (order by project), /* order doesn't appear important so column listed here shouldn't matter */ 
      status, 
      user_id 
    from inserted 

    UPDATE a 
    SET dim_value = i.dim2, 
      last_update = GETDATE(), 
      period_from = i.period_from, 
      period_to = i.period_to, 
      status = i.status, 
      user_id = i.user_id 

    from agldefmatdet a 
    inner join inserted i /* replaces previous where statement */ 
     on i.project = a.att_val_from_1 
     and '11' = a.matrix_id 
     and 'LU' = a.client 

RETURN; 
GO 
+0

こんにちはエドワード、ありがとう - これはNULLエラーを解決しましたが、カーソルはatsprojectテーブルに挿入された複数の行の最後の行を挿入します。私は前にこのエラーがありますが、解決するのは難しいです! – user3565164

+0

こんにちは@ user3565164、私はこのトリガーの例をセットベースのステートメントとして追加しました。テストされていないので、間違いがあるかもしれませんし、意図した通りにうまく動作しないかもしれませんが、より良いテクニックで作業するための基礎を追加できることを願っています。注意:次のステートメントをフェッチして、割り当てを含むように更新する必要があります。 –

+0

ループ内のreturn文を削除してください。トリガーの最後に1つだけを入れてください。 –