>我有一个问题。我正在创建一个触发器,它将提示用户不要创建成本高于其销售成本的采购订单。我已经在我的脚本上声明了一个列,但它仍然显示此错误:
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中,这些称为ASSERTION
s。据我所知,只有 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错误消息是我通常试图避免的事情)