【问题标题】:TSQL variable object reference not set to instance of an objectTSQL 变量对象引用未设置为对象的实例
【发布时间】:2014-02-25 12:04:06
【问题描述】:

我正在尝试创建一个触发器,该触发器在将主记录插入主表时初始化多个表上的记录。下面的代码给出了错误“对象引用未设置为对象的实例。”

Appraisal 是触发器存在的表,每个相关表都有一个 AppraisalID 外键。

BEGIN TRANSACTION
    DECLARE @appraisalid int
    SET @appraisalid = (SELECT AppraisalID FROM inserted)
    INSERT INTO dbo.AppraisalCPD (AppraisalID)
    VALUES (@appraisalid)
COMMIT;

下面的代码有效,但我宁愿使用一个变量来分配值,因为我需要将行添加到相当多的表中。

BEGIN
    INSERT INTO dbo.AppraisalCPD
    (AppraisalID)
    SELECT AppraisalID
    FROM inserted;
END;

如果有人可以建议一种方法来使用 Appraisal 表中的插入行将行插入到我需要的每个其他表中来设置评估 ID 变量,那将非常有帮助。

【问题讨论】:

  • 不能使用单个变量,因为触发器将每条语句触发一次并且可以有多行 Inserted 伪表。您不能将多个值分配给单个变量....
  • SQL Server 没有引发该错误 - 这似乎是导致该问题的 .NET 代码。你能展示你用来生成和执行最终调用这个触发器的插入语句的代码吗?

标签: sql-server tsql variables triggers nullreferenceexception


【解决方案1】:

我假设您在谈论家庭评估。

[appraisal] 表是父表,[owners]/[location] 是子表。

这是 tempdb 中的播放模式。

-- just playing
use tempdb;
go

-- drop table
if object_id('appraisal') > 0
drop table appraisal
go

-- create table - home appraisal 
create table appraisal
(
app_id int identity (1,1),
app_request datetime,
app_employee_id int
);


-- drop table
if object_id('owners') > 0
drop table owners
go

-- create table - the owners
create table owners
(
own_id int identity (1,1) primary key,
own_first_nm varchar(64),
own_last_nm varchar(64), 
app_id int
);


-- drop table
if object_id('location') > 0
drop table location
go

-- the location
create table location
(
loc_id int identity (1,1) primary key,
loc_street varchar(64),
loc_city varchar(64),
loc_state varchar(2), 
loc_zip varchar(9),
app_id int
);
go

通过触发器创建空子记录时,您必须定义默认值或在触发器中提供它们。

另外,我把设置外键留给你处理。

触发器的代码如下所示。

-- The trigger
CREATE TRIGGER DBO.make_empty_children on dbo.appraisal
for insert, update, delete
as
BEGIN

-- nothing to do?
IF (@@rowcount = 0) RETURN;

-- do not count rows
SET NOCOUNT ON;

-- delete
IF NOT EXISTS (SELECT * FROM inserted) 
  BEGIN
    RETURN;
  END

-- insert
ELSE IF NOT EXISTS (SELECT * FROM deleted) 
  BEGIN

-- dummy record for owners
insert into owners
    (
      own_first_nm,
      own_last_nm, 
      app_id
    )
select
  'enter first name',
  'enter last name',
  app_id
from
  inserted;

-- dummy record for location
insert into location
    (
      loc_street,
      loc_city,
      loc_state, 
      loc_zip,
      app_id
    )
select
  'enter street',
  'enter city',
  'ri',
  '00000',
  app_id
from
  inserted;

    RETURN;
  END

  -- update
  ELSE
  BEGIN
      RETURN;
  END

END
GO

我为 DELETE 和 UPDATE 操作留下了占位符。

1 - 您是否要拒绝对评估表中的 id(键)的更新。可能不是。这也可以通过外键 (FK) 来处理(防止)。

2 - 你想级联删除吗?这也可以由 FK 或在触发器中的代码中处理。

让我们看看表中没有记录。

select * from appraisal;
select * from owners;
select * from location;

就像 Marc / Aaron 所说,插入/删除的表是记录集。没有一行。

不保证订单。如果您希望按应用 ID 顺序插入记录,请使用 order by。

-- Insert 2 records
insert into appraisal
(
app_request,
app_employee_id 
)
values
(getdate(), 7),
(dateadd(d, 1, getdate()), 7);

-- Lets see the data
select * from appraisal;
select * from owners;
select * from location;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 2019-03-20
    相关资源
    最近更新 更多