在 SQL Server 中找不到声明后的列



>我有一个问题。我正在创建一个触发器,它将提示用户不要创建成本高于其销售成本的采购订单。我已经在我的脚本上声明了一个列,但它仍然显示此错误:

Msg 207,级别 16,状态 1,过程 _trgZSCheckPrice,第 31 行 [批处理开始行 7]
列名称"fExclPrice"无效

两列分别是@Check@Excl

我在下面附上了我的代码,建议任何帮助:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER _trgZSCheckPrice
ON [dbo].[_btblInvoiceLines] 
FOR INSERT, UPDATE
AS 
BEGIN
SET NOCOUNT ON;
DECLARE
@Valid int,
@ValidPO int,
@DocType int,
@DocState int,
@Check int,
@Excl float,
@POPrice float
SELECT
@Check = ubIICheck,
@Excl = fExclPrice,
@POPrice = fUnitPriceExcl
FROM 
INSERTED
SELECT 
@Excl = fExclPrice,
@Check = ubIICheck 
FROM 
stkitem A 
INNER JOIN 
_etblPriceListPrices B ON A.StockLink = B.iStockID  
SELECT 
@POPrice = fUnitPriceExcl 
FROM 
_btblInvoiceLines C 
LEFT JOIN 
InvNum D ON C.iInvoiceID = D.AutoIndex 
BEGIN
IF (@DocType = 5 AND @DocState <> 7) AND @CHECK = 1
BEGIN
IF @Excl > @POPrice
BEGIN
RAISERROR ('Message from Management: 
You are not allowed to Purchase above Selling Cost.
The transaction will be rolled back. ', 16, 1)
ROLLBACK TRANSACTION
END
END
END 
END

理想情况下,在这里,您将将其实现为多表CHECK约束(实际上,在标准SQL中,这些称为ASSERTIONs。据我所知,只有 Postgre 实现了它们)。

如果您乐于放弃完全控制错误消息的能力,我通常更愿意以声明性方式实现这一点,而不是依赖触发器。

下面介绍如何使用索引视图进行此类检查。首先是几个有点像你的问题域的表格(但不是很充实,因为你没有在你的问题中放任何定义):

create table dbo.ListPrices (
ID int not null,
Price decimal(12,4) not null,
constraint PK_ListPrices PRIMARY KEY (ID)
)
create table dbo.Orders (
ID int not null,
ListPriceID int not null,
MyPrice decimal(12,4) not null,
constraint PK_Orders PRIMARY KEY (ID),
constraint FK_Orders_ListPrices FOREIGN KEY (ListPriceID)
references dbo.ListPrices (ID)
)
go
insert into dbo.ListPrices (ID,Price) values (1,12.50),(2,25.00)

现在我们创建一个特殊的帮助表。如果您的数据库中已有合适的表(例如数字表),则不需要它:

create table dbo.Two (
n int not null,
constraint PK_Two PRIMARY KEY (n),
constraint CK_Two_Only CHECK (n in (1,2))
)
go
insert into dbo.Two (n) values (1),(2)

现在我们创建视图:

go
create view dbo.DRI_NoOrderPricesOverListPrices
with schemabinding
as
select
1 as p /* Constant */
from
dbo.Two t
cross join
dbo.Orders o
inner join
dbo.ListPrices lp
on
o.ListPriceID = lp.ID
where
/*Conditions for failure*/
o.MyPrice > lp.Price
go
create unique clustered index IX_NoOrderPricesOverListPrices
on DRI_NoOrderPricesOverListPrices(p)

这里的关键功能是视图将我们感兴趣的所有表连接在一起,我们可以在where子句中放置我们喜欢的任何条件,引用多个表,比较列值等。

我们指定的条件是针对数据库中不应允许的内容。因此,我们说我们应该能够在Orders中插入一行,前提是其价格小于或等于行项目中的价格。

我们可以。此插入成功:

insert into Orders (ID,ListPriceID,MyPrice) values (1,2,17.00)

而这个失败了:

insert into Orders (ID,ListPriceID,MyPrice) values (2,1,17.00)

Msg 2601,级别 14,状态 1,第 42 行 无法在对象'dbo'中插入重复的键行。DRI_NoOrderPricesOverListPrices",唯一索引"IX_NoOrderPricesOverListPrices"。重复的键值为 (1)。

(正如我在顶部所说,我们无法对错误消息进行太多控制 - 但是在这里选择正确的名称应该可以合理地推断正在发生的事情,并且直接向用户公开SQL Server错误消息是我通常试图避免的事情)

最新更新