长时间读者,第一次来电,以及所有......
以下是业务问题:用户发出一个或多个文档请求。稍后,将文档上载到系统。如果该文档与一个或多个请求匹配,则满足文档请求。因此,例如,可能存在一个或多个对文档A的请求。上传文档A后,将完成对文档A的所有请求。
这是我的技术问题:我在桌面上有一个AFTER INSERT触发器,用于记录文档的上传。它检查DocumentRequest表并更新与上载文档匹配的每一行。如果只有一行匹配(文档A只有一个请求),那么一切都是hunky-dory。但是,如果多个匹配,则触发器中的UPDATE语句失败 - 我看到了这个错误:
子查询返回的值超过1。 这是不允许的 子查询跟随=,!=,<,< =,>,> = 或者子查询用作 表达
以下是相关表格的CREATE语句:
CREATE TABLE [dbo].[DocumentRequest](
[DocumentRequestId] [int] IDENTITY(1,1) NOT NULL,
[BatchID] [int] NULL,
[CertificateNum] [varchar](20) NOT NULL,
[RequestedTypCd] [varchar](5) NULL,
[RequestedReason] [varchar](60) NULL,
[DestinationTypCd] [varchar](5) NULL,
[DocumentPackageTypCd] [varchar](5) NULL,
[RequestedDtm] [datetime] NOT NULL,
[RequestNotes] [varchar](1000) NULL,
[RequestStatusTypCd] [varchar](5) NOT NULL,
[InactiveFlag] [char](1) NULL,
[CreationDtm] [datetime] NOT NULL,
[CreationUserID] [varchar](10) NOT NULL,
[CompletedDtm] [datetime] NULL,
[CompletedUserID] [varchar](10) NULL,
[ModifiedDtm] [datetime] NULL,
[ModifiedUserID] [varchar](10) NULL,
CONSTRAINT [XPKDocumentRequest] PRIMARY KEY NONCLUSTERED
(
[DocumentRequestId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
--------------
CREATE TABLE [dbo].[DocumentRequestContents](
[DocumentTypCd] [varchar](5) NOT NULL,
[CreationDtm] [datetime] NOT NULL,
[CreationUserID] [varchar](10) NOT NULL,
[DocumentRequestId] [int] NOT NULL,
[DocumentReceivedDtm] [datetime] NULL,
[DocumentReceivedFlag] [char](1) NULL,
[DocumentIgnoreFlag] [char](1) NULL,
CONSTRAINT [XPKDocumentRequestContents] PRIMARY KEY NONCLUSTERED
(
[DocumentRequestId] ASC,
[DocumentTypCd] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
--------------
CREATE TABLE [dbo].[DocumentStorage](
[DocumentStorageID] [int] IDENTITY(1,1) NOT NULL,
[CertificateNum] [varchar](10) NULL,
[DocumentHandleID] [int] NULL,
[DocumentTypVal] [varchar](100) NULL,
[CreationDtm] [datetime] NULL,
[CreationUserID] [varchar](10) NULL,
[lastupd_user] [varchar](8) NULL,
[lastupd_stamp] [datetime] NULL,
[DocumentNam] [varchar](100) NULL,
PRIMARY KEY NONCLUSTERED
(
[DocumentStorageID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
--------------
CREATE TABLE [dbo].[DocumentProfile](
[DocumentProfileID] [int] IDENTITY(1,1) NOT NULL,
[DocumentTypCd] [varchar](5) NULL,
[DocumentVersionNum] [varchar](10) NULL,
[DocumentApproveInd] [varchar](1) NULL,
[CreationDtm] [datetime] NULL,
[CreationUserID] [varchar](10) NULL,
[lastupd_stamp] [datetime] NULL,
[lastupd_user] [varchar](8) NULL,
[DocumentStorageTypVal] [varchar](100) NULL,
[MIMETypVal] [varchar](50) NULL,
[DocumentSourceTypCd] [varchar](5) NULL,
[DocumentFormatTypCd] [varchar](5) NULL,
[DocumentReceiveLocationTypCd] [varchar](5) NULL,
[DocumentIndexTypCd] [varchar](5) NULL,
[DocumentNam] [varchar](100) NULL,
[DocumentTrackedInd] [char](1) NULL CONSTRAINT [DF_DocumentProfile_DocumentTrackedInd] DEFAULT ('N'),
PRIMARY KEY NONCLUSTERED
(
[DocumentProfileID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
触发器......
CREATE TRIGGER [trg_DMTDocumentReceived_DocumentStorage]
ON [dbo].[DocumentStorage]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE DocumentRequestContents
SET DocumentRequestContents.DocumentReceivedFlag = 'Y',
DocumentRequestContents.DocumentReceivedDtm = getdate()
FROM
DocumentRequestContents
INNER JOIN DocumentRequest
ON DocumentRequestContents.DocumentRequestId = DocumentRequest.DocumentRequestId
INNER JOIN DocumentProfile
ON DocumentRequestContents.DocumentTypCd = DocumentProfile.DocumentTypCd
INNER JOIN Inserted
ON DocumentProfile.DocumentStorageTypVal = Inserted.DocumentTypVal
WHERE
(DocumentRequestContents.DocumentReceivedFlag <> 'Y' OR
DocumentRequestContents.DocumentReceivedFlag IS NULL)
AND (DocumentRequest.InactiveFlag IS NULL)
AND (DocumentRequest.CertificateNum = Inserted.CertificateNum)
AND (DocumentProfile.DocumentStorageTypVal = Inserted.DocumentTypVal)
END
从这里开始,我有点不知所措。你能帮一个人吗?
修改 请求可以有多个文档,因此触发器中正在更新的表(DocumentRequestContents)上也有一个触发器,它确定是否已满足整个请求。据我所知,它也没有子查询,但这里是:
CREATE TRIGGER [trg_DMTDocumentReceived_CompletenessCheck]
ON [dbo].[DocumentRequestContents]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @TotalDocs int, @ReceivedDocs int
IF UPDATE(DocumentReceivedFlag)
BEGIN
IF (SELECT DocumentReceivedFlag FROM Inserted) = 'Y' AND (SELECT DocumentReceivedFlag FROM Deleted) = 'N'
BEGIN
SELECT @TotalDocs = count(*)
FROM DocumentRequestContents
INNER JOIN Inserted
ON DocumentRequestContents.DocumentRequestID = Inserted.DocumentRequestID
WHERE (DocumentRequestContents.DocumentIgnoreFlag <> 'Y' OR DocumentRequestContents.DocumentIgnoreFlag IS NULL)
SELECT @ReceivedDocs = count(*)
FROM DocumentRequestContents
INNER JOIN Inserted
ON DocumentRequestContents.DocumentRequestID = Inserted.DocumentRequestID
WHERE DocumentRequestContents.DocumentReceivedFlag = 'Y'
IF (@ReceivedDocs = @TotalDocs)
BEGIN
UPDATE DocumentRequest
SET RequestStatusTypCd = 'CMPLT',
CompletedDtm = getdate(),
CompletedUserID = 'SYSTEM',
ModifiedDtm = getdate(),
ModifiedUserID = 'SYSTEM'
FROM DocumentRequest
INNER JOIN Inserted
ON DocumentRequest.DocumentRequestId = Inserted.DocumentRequestId
END
END
END
END
谢谢, 杰森
答案 0 :(得分:3)
违规行似乎在这里:
IF (SELECT DocumentReceivedFlag FROM Inserted) = 'Y' AND
(SELECT DocumentReceivedFlag FROM Deleted) = 'N' ...
这基本上是一个“子查询”。编写IF
语句时期望inserted
和deleted
中只有一行。在不知道业务逻辑在这里的细节的情况下,我只能推测,但如果您只是将其重写为:
IF EXISTS(SELECT 1 FROM inserted WHERE DocumentReceivedFlag = 'Y') AND
EXISTS(SELECT 1 FROM deleted WHERE DocumentReceivedFlag = 'N'))
但它可能比那更复杂......可能你实际上需要将插入的行连接到已删除的行并检查标志是否实际上已从'Y'更改为'N'。
答案 1 :(得分:1)
检查DocumentRequestContents是否也没有触发器。
答案 2 :(得分:1)
重新阅读时,明显的问题是第二次触发的这一部分:
IF (SELECT DocumentReceivedFlag FROM Inserted) = 'Y'
AND (SELECT DocumentReceivedFlag FROM Deleted) = 'N'
如果插入了多行,则会失败,因为SQL Server希望这两个子查询都返回一行或没有行。
顺便说一下,我个人不惜一切代价避免使用触发器。它们给我带来了太多的复杂性。
答案 3 :(得分:0)
您可能希望尝试对联接中的Inserted
表进行别名处理。虽然我自己没有经历过这种情况,但它可能会尝试在WHERE
子句中执行子查询,而不是使用连接表。
答案 4 :(得分:0)
您的触发器似乎在其中的任何位置都没有子查询 - 这是您桌面上唯一的触发器?此错误不是由连接或多行更新引起的,因此我不知道为什么您的触发器会产生此错误。
当您尝试插入表格本身时,是否收到错误?也许它实际上是你用来插入失败的查询 - 请发布那个插入语句。