2017-12-12 10 views
0

PersonalInfoというテーブルの挿入後にトリガーを書き込もうとしています。 GenderIDとidは、テーブルGenderとRegisterationFormの外部キーです。トリガーAFTER INSERT結果がログテーブルにNULLを挿入できません

DBLogは、トリガーアクションを記録するために使用するテーブルです。

これは私が書いたものである:

Create Trigger [dbo].[InsertPersonalInfoTrigger] ON [dbo].[PersonalInfo] 
after Insert 
as 
begin 
declare @Name nvarchar(50) 
declare @FamilyName nvarchar(50) 
declare @FatherName nvarchar(50) 
declare @BirthDate nchar(10) 
declare @GenderID int 
declare @NationalId nvarchar(50) 
declare @id int 


select @Name=Max(@Name),@FamilyName=Max(@FamilyName),@FatherName=Max(@FatherName),@BirthDate=Max(@BirthDate) 
,@GenderID=Max(@GenderID),@NationalId=Max(@NationalId),@id=Max(@id) 
    from Inserted 
if(@Name='') 
begin 
    RAISERROR ('Enter the Name', 
      16, 
      1 
      ); 
    RollBack 
    return; 
end 
declare @LogID int 
set @LogID= (select isnull(max(LogID),0) from DBLog) +1 

declare @ActionDes varchar(2000); 
set @ActionDes = 'Insert Into Gender INNER JOIN 
        PersonalInfo ON Gender.GenderID = PersonalInfo.GenderID INNER JOIN 
        RegisterationForm ON PersonalInfo.id = RegisterationForm.id(Name,FamilyName,FatherName,BirthDate,GenderID,NationalId,id) 
        Values("' + @Name + '","' + @FamilyName + '","' + @FatherName + '","' + @BirthDate + '",'+cast(@GenderID as varchar(20))+ ', 
        "' + @NationalId +'",'+cast(@id as varchar(20))+ ')'; 
declare @dt datetime; 
set @dt=getdate(); 

declare @usr varchar(50); 
select @usr =current_user 

insert into DBLog(LogID,ActionDes,ActionTime,ActionUser) 
    values (@LogID,@ActionDes,@dt,@usr) 
end 
Go 

トリガを実行した後、私は私のPersonalInfoテーブルにデータを挿入しようとすると、私は次のエラーを取得する:

No row was updated

The data in row 5 was not comitted

Error Source: .Net SqlClient Data Provider.

Error Message: Cannot insert the value NULL into column 'ActionDes', table '.dbo.DBLog'; column does not allow nulls.INSERT fails.

Warning: Null value is eliminated by an aggregate or other SET operation.

The statement has been terminated.

それは私は事実です私のActionDesカラムにNULLを許さないのですが、ここで私はデータを挿入しています。 NULLはどこから来ますか?どうしたの?

+3

ここには多くの問題があります。 「行5」は複数の行を挿入していることを示していますが、挿入された表には1つの行しかないかのように動作するようにトリガーがコーディングされていますか?今のところ、ロギングテーブルのフィールドには、デバッグに役立つNULLを許可することをお勧めします。また、psuedo-sql *を構成する代わりに、各フィールドを別々に格納することをお勧めします(文字列をデリミートすることは決して実行できないことを意味します)*すべての値を保持する*実際には**** – MatBailie

+0

@MatBailieトリガーを作成する前に4行挿入しました。そのため、5行目と言いました。 –

答えて

3

「ふりがな」挿入文を構成する文字列を格納しないでください。テーブルに挿入する方法は数多くありますが、使用する形式を推測しているのは悪い考えです。

また、1つの行だけが挿入されていることを前提としています。これは、間違った仮定です。insertedテーブルから複数の行を読み込むようにコードを変更してください。

ログにはNULLを許可します。 nameフィールドが[personalInfo]テーブルのNULLでない場合は、フィールドNOT NULLを作成します。トリガーを使用してチェック制約を実施しないでください。

idを取得するためにロギングテーブルを読み取ってから値を増やさないで、idカラムをIDENTITYカラムにして、それをデータベースで管理させます。競合状態があり、値を読み取ることができます。次に他のプロセスが行を挿入した後、行を挿入して競合を生成しようとします。それは本当に悪い習慣です。

CREATE [dbo].[InsertPersonalInfoTrigger] ON [dbo].[PersonalInfo] 
    AFTER INSERT 
AS 
BEGIN 

    INSERT INTO 
     DBLog (
     ActionDes, 
     ActionTime, 
     ActionUser 
    ) 
    SELECT 
     ISNULL('"' + CAST(inserted.ID   AS NVARCHAR(128) + '"', 'NULL') + ' AS id, ' + 
     ISNULL('"' + CAST(inserted.Name  AS NVARCHAR(128) + '"', 'NULL') + ' AS name, ' + 
     ISNULL('"' + CAST(inserted.FamilyName AS NVARCHAR(128) + '"', 'NULL') + ' AS FamilyName, ' + 
     ISNULL('"' + CAST(inserted.FatherName AS NVARCHAR(128) + '"', 'NULL') + ' AS FatherName, ' + 
     ISNULL('"' + CAST(inserted.BirthDate AS NVARCHAR(128) + '"', 'NULL') + ' AS BirthDate, ' + 
     ISNULL('"' + CAST(inserted.GenderID AS NVARCHAR(128) + '"', 'NULL') + ' AS GenderID, ' + 
     ISNULL('"' + CAST(inserted.NationalId AS NVARCHAR(128) + '"', 'NULL') + ' AS NationalID', 
     GETDATE(), 
     CURRENT_USER 
    FROM 
     inserted 
     -- There could be many rows in this table, don't pretend or assume there will only be one 
END 

GO 

ベターはまだ、あなたが[PersonalInfo]から録音している各フィールドの個別のログフィールドを持っています。たとえそれが汎用のDBLogテーブルと別のDBLogPersonalInfoテーブルを持つことを意味しています。

CREATE [dbo].[InsertPersonalInfoTrigger] ON [dbo].[PersonalInfo] 
    AFTER INSERT 
AS 
BEGIN 

    INSERT INTO 
     DBLog (
      ActionDes, 
      ActionTime, 
      ActionUser 
     ) 
    VALUES (
     'INSERT INTO [dbo].[PersonalInfo]', 
     GETDATE(), 
     CURRENT_USER 
    ); 

    INSERT INTO 
     DBLogPersonalInfo (
      DBLogID, 
      id, 
      Name, 
      FamilyName, 
      FatherName, 
      BirthDate, 
      GenderID, 
      NationalID 
     ) 
    SELECT 
     SCOPE_IDENTITY(), -- The latest value from the IDENTITY column of `DBlog` (as created by THIS process). 
     inserted.ID, 
     inserted.Name, 
     inserted.FamilyName, 
     inserted.FatherName, 
     inserted.BirthDate, 
     inserted.GenderID, 
     inserted.NationalID 
    FROM 
     inserted 

    -- No need for `CAST` or `ISNULL`. 
    -- Now you can even join DBLogPersonalInfo to PersonalInfo and compare changes (programatically) 
    -- Simpler, more reliable, and more flexible... 

END 

GO 
3

トリガーの権利を理解している場合、挿入された表の各行について、@変数=最大(@変数)を設定しています。変数に値を割り当てていないので、すべての変数値はまだnullです。

連結ルールでは、NULL値との連結がNULL値と等しいことが必要なため、パラメータ値のいずれかがNULLの場合は@ActionDes変数がnull値になり、試行時にエラーをスローします。 DBLogテーブルに挿入します。

+0

「@名前=最大(名前)、@ FamilyName = Max(ファミリー名)...」のように選択する必要がありますが、@MatBailieにも良いアドバイスがあります。挿入されたテーブルのすべての行に集計されているわけではありませんので、挿入されたテーブルのすべての行に集計されますので、単列の挿入では複数行挿入の混乱が発生します –

+0

いいえcatch @Wes H. "Max @variable) "と読み替えて、代わりにMAX()と読んでください。私はあなたの応答をupvoted!:) –

+0

私は外部キーを持っていない別のテーブルのための同じトリガを使用し、それは正常に動作し、DBLogテーブルのデータが正しいです。 –

1

物事のカップル:

  1. ここでは述べたように、「Warning: Null value is eliminated by an aggregate or other SET operation.
  2. あなたのトリガを挿入した後、いない更新後に書かれている、上で良い記事です。
  3. 最後に、あなたの値(MAX())FROM INSERTEDはすべてNULLではないと仮定しています。そうでないかもしれない。それぞれの変数の周りにISNULL(、N '')またはCOALESCE(、N ")を付けて@actionDesを集計してみてください。"エラーメッセージ:NULL値を列 'ActionDes'に挿入できません。 、テーブル '.dbo.DBLog';列はnulls.INSERTが失敗することを許可しません。

INSERTEDで集計を実行する理由はわかりませんが、私が述べたことはあなたが言及した問題に対処すると考えています。

関連する問題