The database I am working on has the following insert trigger. The problem is the trigger will not work with a multi-row insert. When I try and insert more than one row at a time I get the following message.
Msg 512, Level 16, State 1, Procedure _ti_UD06, Line 8
Subquery returned more than 1 value. This is not permitted when the subquery
follows =, !=, <, <= , >, >= or when the subquery is used as an
expression. I think the problem is with the following statement it
will return more than one value when multiple rows are inserted.
How can I make this insert trigger work with multiple rows?
IF(SELECT PROGRESS_RECID FROM inserted) IS NULL
There are 2 columns in the table, PROGRESS_RECID and PROGRESS_RECID_IDENT_.
I think the PROGRESS_RECID_IDENT_ is an Identity column for SQL Server. The PROGRESS_RECID_INDENT is used by the PROGRESS Server.
If a new record is inserted the trigger checks to see if the PROGRESS_RECID is null and will set it to the inserted.Identity
ALTER trigger [dbo].[_ti_UD06] ON [dbo].[UD06] for insert as
begin
if ( select PROGRESS_RECID from inserted) is NULL
begin
update t set PROGRESS_RECID = i.IDENTITYCOL
from UD06 t JOIN INSERTED i ON
t.PROGRESS_RECID_IDENT_ = i.PROGRESS_RECID_IDENT_
select convert (bigint, ##identity)
end
end
Here is the Table definition
CREATE TABLE [dbo].[UD06](
[Company] [nvarchar](8) NULL,
[Key1] [nvarchar](50) NOT NULL,
[Key2] [nvarchar](50) NULL,
[Key3] [nvarchar](50) NULL,
[Key5] [nvarchar](50) NULL,
[Character01] [nvarchar](max) NULL,
[Character02] [nvarchar](max) NULL,
[Character03] [nvarchar](max) NULL,
[Character04] [nvarchar](max) NULL,
[Character05] [nvarchar](max) NULL,
[Character06] [nvarchar](max) NULL,
[Character07] [nvarchar](max) NULL,
[Character08] [nvarchar](max) NULL,
[Character09] [nvarchar](max) NULL,
[Character10] [nvarchar](max) NULL,
[SysRowID] [nvarchar](36) NULL,
[SysRevID] [int] NULL,
[BitFlag] [int] NULL,
[GlobalUD06] [tinyint] NULL,
[GlobalLock] [tinyint] NULL,
[PROGRESS_RECID] [bigint] NULL,
[PROGRESS_RECID_IDENT_] [bigint] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]
I think you're pretty close already:
ALTER trigger [dbo].[_ti_UD06] ON [dbo].[UD06] for insert as
begin
UPDATE t
SET PROGRESS_RECID = t.PROGRESS_RECID_IDENT_ --not "IDENTITYCOL"
FROM UD06 t
JOIN inserted i ON t.PROGRESS_RECID_IDENT_ = i.PROGRESS_RECID_IDENT_
WHERE i.PROGRESS_RECID is Null
-- Not sure what this bit is for? I doubt it's a good idea though...
select convert (bigint, ##identity)
end
Related
I know this question has already been answered a lot, but I can't find the mistake.
I'm getting the following error:
Types don't match between the anchor and the recursive part in column "Parent" of recursive query "GroupHierarchy".
This is the query:
WITH GroupHierarchy (UserGroupName, UserGroupID, IsGroup, Parent, Level)
AS
(
-- Anchor member definition
SELECT ug.UserGroupName, ug.UserGroupID, ug.IsGroup, CAST('' as nvarchar(MAX)) as Parent, 0 AS Level
FROM KnowledgeVaultMaster.dbo.UserGroup AS ug
WHERE ug.IsGroup = 0
UNION ALL
-- Recursive member definition
SELECT ug.UserGroupName, ug.UserGroupID, ug.IsGroup, CAST(gh.UserGroupName as nvarchar(MAX)) as Parent, Level + 1
FROM KnowledgeVaultMaster.dbo.UserGroup AS ug
JOIN KnowledgeVaultMaster.dbo.UserGroupGroup AS ugg
ON ug.UserGroupID = ugg.ParentUserGroupId
INNER JOIN GroupHierarchy gh
ON ugg.UserGroupId = gh.UserGroupID
)
-- Statement that executes the CTE
SELECT UserGroupName, UserGroupID, IsGroup, Parent, Level
FROM GroupHierarchy
The original column UserGroup.UserGroupName is nvarchar(255), not null
EDIT: These are the tables (constraints and defaults omitted):
CREATE TABLE [dbo].[UserGroup](
[UserGroupID] [bigint] IDENTITY(1,1) NOT NULL,
[UserGroupName] [nvarchar](255) NOT NULL,
[SystemName] [nvarchar](50) NULL,
[UserPassword] [nvarchar](50) NULL,
[Salt] [nvarchar](20) NULL,
[IsGroup] [tinyint] NOT NULL,
[SuperUser] [bit] NOT NULL,
[FirstName] [nvarchar](50) NULL,
[LastName] [nvarchar](100) NULL,
[Email] [nvarchar](100) NULL,
[CreateDate] [datetime] NOT NULL,
[CreateUserID] [bigint] NOT NULL,
[AuthType] [int] NOT NULL,
[Active] [bit] NOT NULL
) ON [PRIMARY] GO
CREATE TABLE [dbo].[UserGroupGroup](
[UserGroupId] [bigint] NOT NULL,
[ParentUserGroupId] [bigint] NOT NULL
) ON [PRIMARY] GO
Finally I found the problem. The database was imported with compatibility level SQL Server 2012 (110).
I changed it to SQL Server 2016 (130) and now the cte works.
I have a Test table
CREATE TABLE [dbo].[Test](
[TestId] [int] IDENTITY(1,1) NOT NULL,
[TestName] [nvarchar](50) NOT NULL,
[UserId] [int] NOT NULL,
[isDelete] [bit] NOT NULL,
and Questions table as
CREATE TABLE [dbo].[Questions](
[Qid] [int] IDENTITY(1,1) NOT NULL,
[Tid] [int] NOT NULL,
[Qtype] [int] NOT NULL,
[Question] [nvarchar](max) NOT NULL,
[isDelete] [bit] NULL,
Questions table stores all the questions for each test with Tid as foreign key.
I want to write a stored procedure to fetch TestName, TestId and number of questions in each test in a single stored procedure. But I am unable to get this.
You can write the stored procedure as:
CREATE PROCEDURE [dbo].[procGetNumberofQuestionsForTest]
AS
BEGIN
SELECT T.[TestId], T.[TestName], COUNT(Q.[Qid]) AS NumberOfQuestions
FROM [dbo].[Test] T
JOIN [dbo].[Questions] Q ON Q.Tid = T.TestId
GROUP BY T.[TestId], T.[TestName]
END
If you want to get the result for specific Test, then pass the parameter as #TestId INT and add the WHERE clause as WHERE T.[TestId] = #TestId before the GROUP BY.
Try this (table create, insert, proc creation and execution included);
CREATE TABLE [dbo].[Test](
[TestId] [int] IDENTITY(1,1) NOT NULL,
[TestName] [nvarchar](50) NOT NULL,
[UserId] [int] NOT NULL,
[isDelete] [bit] NOT NULL)
go
CREATE TABLE [dbo].[Questions](
[Qid] [int] IDENTITY(1,1) NOT NULL,
[Tid] [int] NOT NULL,
[Qtype] [int] NOT NULL,
[Question] [nvarchar](max) NOT NULL,
[isDelete] [bit] NULL
)
go
insert into [dbo].[Test]
values('test #1',1,0)
go
insert into [dbo].[Questions]
values(1,1,'what is life',0)
go
create proc dbo.MyInfo
as
select
t.TestName,
t.TestId,
[No Questions]=COUNT(q.Qid)
from
[dbo].[Test] t
inner join
[dbo].[Questions] q on t.TestId=q.Qid
group by
t.TestName,
t.TestId
go
exec dbo.MyInfo
go
I have these tables :
CREATE TABLE [dbo].[FileISOManagers]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[LineId] [int] NOT NULL,
[Revision] [nvarchar](max) NULL,
[FileName] [nvarchar](max) NULL,
[UserId] [int] NOT NULL,
[SubmitDateTime] [datetime] NOT NULL
)
CREATE TABLE [dbo].[Lines]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[LineNumber] [nvarchar](max) NULL,
[DocumentNumber] [nvarchar](max) NULL,
[Revision] [nvarchar](max) NULL
)
Every line has multiple revisions, so I just need to insert the last revision column value in FileISOManagers table inside Revision column in lines table automatically. I want do this in SQL Server. Is there any solution to do this? Should I use a trigger?
revision
-- Create trigger on table FileISOManagers for Insert statement
CREATE TRIGGER trgAfterInsert on FileISOManagers
FOR INSERT
AS declare #Revision varchar(100);
select #Revision=i.Revision from inserted i;
set #action='Inserted Record -- After Insert Trigger.'; insert into Lines(Revision)
values (#Revision);
PRINT 'AFTER INSERT trigger fired.
It can be done using joins and alias.
Example
INSERT INTO FileISOManagers (Revision ..columns)
SELECT *
FROM Lines ls
WHERE NOT EXISTS
(
SELECT *
FROM FileISOManagers
WHERE LineId = ls.id
) order by ls.id desc
i have two tables:
1.
CREATE TABLE [dbo].[HotelSourceMap](
[hotelsourcemapid] [bigint] IDENTITY(1,1) NOT NULL,
[dspartnerid] [bigint] NOT NULL,
[dshotelid] [bigint] NOT NULL,
[countrycode] [varchar](5) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[countryid] [bigint] NULL)
2.
CREATE TABLE [dbo].[country](
[countryId] [smallint] IDENTITY(1,1) NOT NULL,
[countryName] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[countryCode] [varchar](2) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL)
situation is like this:
i want to update countryid in HotelSourceMap table from country.countryid .
where hotelsourcemap.countrycode = country.countrycode
some thing like this:
UPDATE HotelSourceMap
SET
HotelSourceMap.countryid =country.countryId
WHERE
HotelSourceMap.countrycode = country.countryCode
There's probably a set-based solution for this, in which case that would be preferable, and I'm sure someone will post it, but until then, at least this will do the job:
UPDATE
HotelSourceMap
SET
countryid = (SELECT countryId FROM country WHERE country.countryCode = HotelSourceMap.countrycode)
This is really questionable table design, but here is the SQL:
UPDATE HotelSourceMap
SET countryid = co.countryId
FROM HotelSourceMap AS hsm
JOIN country AS co
ON (hsm.countryCode = co.countryCode)
Long time reader, first time caller, and all that...
Here's the business problem: a user makes one or more requests for documents. At some later time, a document is uploaded to the system. If that document matches one or more of the requests, the document request is fulfilled. So, there could be one or many requests for Document A, for instance. When Document A is uploaded, all of the requests for Document A are fulfilled.
And here's my technical problem: I've got an AFTER INSERT trigger on the table where the upload of the document is recorded. It checks the DocumentRequest table and updates each row that matches the uploaded document. If only one row matches (only one request for Document A), everything is hunky-dory. If, however, more than one matches, the UPDATE statement in the trigger fails -- I see this error:
Subquery returned more than 1 value.
This is not permitted when the
subquery follows =, !=, <, <= , >, >=
or when the subquery is used as an
expression.
Here are the CREATE statements for the relevant tables:
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]
And the trigger...
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
I'm at a bit of a loss as to where to go from here. Can you give a guy a hand?
EDIT:
A request can have more than one document, so the table that is being updated in the trigger (DocumentRequestContents) also has a trigger on it, which determines if the entire request has been fulfilled. As far as I can tell, it does not have a subquery, either, but here it is:
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
Thanks,
Jason
The offending line appears to be here:
IF (SELECT DocumentReceivedFlag FROM Inserted) = 'Y' AND
(SELECT DocumentReceivedFlag FROM Deleted) = 'N' ...
This is essentially a "subquery". The IF statement is written with the expectation that there will only be one row in both inserted and deleted. Without knowing the details of what the business logic is here, I can only speculate, but most likely you'll be OK if you just rewrite that as:
IF EXISTS(SELECT 1 FROM inserted WHERE DocumentReceivedFlag = 'Y') AND
EXISTS(SELECT 1 FROM deleted WHERE DocumentReceivedFlag = 'N'))
But it might be more complicated than that... it could be that you actually need to join the inserted to deleted rows and check if the flag has actually changed from 'Y' to 'N'.
Check if you don't have a trigger on DocumentRequestContents as well.
On re-reading, the obvious problem is this part of the second trigger:
IF (SELECT DocumentReceivedFlag FROM Inserted) = 'Y'
AND (SELECT DocumentReceivedFlag FROM Deleted) = 'N'
This would fail if multiple rows where inserted, because SQL Server expects both of these subqueries to return one or no rows.
By the way, I personally avoid triggers at any cost. They introduce too much complexity for me to handle.
You may want to try aliasing the Inserted table in your join. While I haven't experienced this myself, it may be attempting to perform a subquery in your WHERE clause rather than using the joined table.
Your trigger doesn't appear to have a sub-query anywhere in it - this is the only trigger on your table? This error isn't caused by a join or a multi-row update, so I'm at a loss as to why your trigger would be generating this error.
Do you get the error when you're attempting the insert into the table itself? Perhaps it's actually the query you're using to insert that's failing - please post that insert statement as well.