Stored procedure throws an error on my subquery - sql-server

My database trigger takes a date from a column and adds 60 days to it and stores it into another column.
And it does as expected when I execute the code in query window and it throws the following error.
Msg 512, Level 16, State 1, Line 4
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
My code:
DECLARE #NextDate date
SELECT #NextDate = (SELECT DATEADD(day, 10, Today) FROM Test)
INSERT INTO Test (Notes, Today)
VALUES ('Testing in Query2', GETDATE())
DECLARE #newint int
SET #newint = SCOPE_IDENTITY()
UPDATE Test
SET Someday = #NextDate
WHERE ID = #newint
RESULT
But keeps giving the error with the result.
Msg 512, Level 16, State 1, Line 4
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

INSERT INTO #NextDate SELECT DATEADD(day,10,Today) FROM Test

In Your Query
SELECT #NextDate = (SELECT DATEADD(day,10,Today) FROM Test)
the sub query returning more than one value and you cant assign the multiple values to one variable. this is causing the problem in you query.
As Dominic Deepan.d Suggested use the where condition
SELECT #NextDate = (SELECT DATEADD(day,10,Today) FROM Test WHERE ID = #newint)
Or else try the same in another way
SELECT #NextDate = DATEADD(day,10,Today) FROM Test WHERE ID = #newint

Well Finally i sorted it out, Silly me :D
INSERT INTO Test(Notes,Today)
values ('Testing in Query3',GETDATE())
DECLARE #newint int
SET #newint = SCOPE_IDENTITY()
DECLARE #NextDate date
SELECT #NextDate = (SELECT DATEADD(day,10,Today) FROM Test WHERE ID = #newint)
UPDATE Test
SET Someday = #NextDate
WHERE ID = #newint
GO
I juz had to put WHERE in this line
SELECT #NextDate = (SELECT DATEADD(day,10,Today) FROM Test WHERE ID = #newint)

Related

Conversion of scalar variable in query

I am working with public database Wide World Importers and I try to make some query.For input in this query I want to use scalar variables. You can see code below:
DECLARE #SupplierID int = 7
DECLARE #YearMonth NVARCHAR = '2013.1'
SELECT
pur.SupplierID, SUM(purst.TransactionAmount) AS TotalTransaction,
CONCAT(YEAR(pur.OrderDate), '.', MONTH(pur.OrderDate)) AS YearMonth
FROM
[Purchasing].[PurchaseOrders] AS pur
INNER JOIN
[Purchasing].[SupplierTransactions] AS purst ON purst.SupplierID = pur.SupplierID
WHERE
pur.SupplierID = #SupplierID
AND YearMonth = #YearMonth
GROUP BY
pur.OrderDate, pur.SupplierID
Above code work well and give me good result (but without scalar variable #YearMonth). You can see result below:
But when I try to include YearMonth like scalar variable into this query I get this error:
Msg 207, Level 16, State 1, Line 3831
Invalid column name 'YearMonth'
So can anybody help me how to fix this problem and make query properly?
You can't reference a column declared in the SELECT in the WHERE. You need to reference the actual columns in the table in the WHERE, or use a subquery or CTE.
What you should be doing here, however, is using proper date logic:
DECLARE #SupplierID int = 7,
#StartDate date = '20130101',
#EndDate date = '20130201';
SELECT PO.SupplierID,
SUM(ST.TransactionAmount) AS TotalTransaction,
CONCAT(YEAR(PO.OrderDate), '.', MONTH(PO.OrderDate)) AS YearMonth
FROM [Purchasing].[PurchaseOrders] PO
INNER JOIN [Purchasing].[SupplierTransactions] ST ON ST.SupplierID = PO.SupplierID
WHERE PO.SupplierID = #SupplierID
AND PO.OrderDate >= #StartDate
AND PO.OrderDate < #EndDate
GROUP BY PO.OrderDate,
PO.SupplierID;
I also change your aliases to something a bit more appropriate.

Create Insert Trigger

This is my code:
USE MyGuitarshop
GO
CREATE TRIGGER Products_INSERT
ON Products
FOR INSERT
AS
BEGIN
UPDATE Products
SET DateAdded = GETDATE()
WHERE DateAdded IS NULL;
END;
GO
USE MyGuitarShop
INSERT INTO Products (CategoryID, ProductCode, ProductName, Description, ListPrice, DiscountPercent, DateAdded)
VALUES (1, '229985', 'Quartz Watch', 'Lovely watch with a quartz face', 29.99, 12, NULL);
GO
USE MyGuitarShop
SELECT * FROM Products
It pops this error: Msg 512, Level 16, State 1, Procedure Products_UPDATE, Line 13 [Batch Start Line 21]
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I don't understand the error or how to fix it. Can someone please point me in the right direction?
You cannot use the regular comparison operators with NULL - anything compared to NULL is undefined and therefore "false".
The only thing you can do to check with NULL is to use IS NULL or IS NOT NULL :
UPDATE Products
SET DateAdded = GETDATE()
WHERE DateAdded IS NULL;
Try
UPDATE inserted SET DateAdded = GETDATE() WHERE DateAdded IS NULL; END;

INSERT SELECT SQL Query with Variables

I am trying to INSERT record(s) where some of the fields in the record(s) come from one table and the rest of the fields are created from variables. Here is the INSERT SELECT query where I am trying to create the record(s):
DECLARE #projid INT
,#status INT
,#created DATETIME
,#duedate DATETIME
,#numdays INT
,#divid INT
SET #divid =
(SELECT DIVID
FROM DIV
WHERE StepOrder=1)
SET #numdays =
(SELECT CompTarget
FROM DIV
WHERE DIVID=#divid)
SET #projid = 10
SET #status = 0
SET #duedate =
DATEADD(day,#numdays,#created)
SET #created = '4/18/2017'
INSERT INTO DIVTasks (ProjectID, GroupID, Status, Created, DueDate, DIVID)
SELECT #projid, GroupID, #status, #created, #duedate, DIVID
FROM DIV
WHERE StepOrder=1
There are 3 records with the StepOrder the equals 1 and they have different "CompTarget" numbers.
What I need it to do is take the "Created" date add the "CompTarget" number and return the "DueDate" for each record.
The above query returns this error but does enter 3 records with the "DueDate" as Null:
Msg 512, Level 16, State 1, 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.
Both
SET #divid =
(SELECT DIVID
FROM DIV
WHERE StepOrder=1)
and
SET #numdays =
(SELECT CompTarget
FROM DIV
WHERE DIVID=#divid)
will cause the same error, since you wrote there are 3 records with StepOrder equals 1 in that table.
However, I think you are over complicating things.
Try this insert....select instead:
DECLARE #projid INT = 10
,#status INT = 0
,#created DATETIME = '2017-04-18' -- note the change of format here!
INSERT INTO DIVTasks (ProjectID, GroupID, Status, Created, DueDate, DIVID)
SELECT #projid, GroupID, #status, #created, DATEADD(day,CompTarget,#created), DIVID
FROM DIV
WHERE StepOrder=1
Note - using yyyy-mm-dd as the date's string representation format makes it unambiguous.

Is it possible to have a view in sql-server 2008 that splits one row into many?

The back story is I am trying to write a view that takes a table who's every row is an ID and serialized data for that ID in a clob and presents it in sql navigable form. basically my code looks like:
CREATE VIEW UNSERIALIZED_TABLE_VIEW AS
SELECT
SOURCE_TABLE.ID SOURCE_ID,
a.*
FROM
SOURCE_TABLE,
FUNCTION_WHICH_UNSERIALIZES((SELECT DATA FROM SOURCE_TABLE WHERE ID = SOURCE_ID)
I tried putting the function in the select statement, but that just gave a syntax error about it being undefined. When it runs the error is usually about a subquery returning too many values. I could just unserialize the data in batches, but now I'm really curious what's going wrong.
Example Data
#0History:23:ALPHANUMERICSTUFF1234567ID:11:ACCT1234567SourceMode:6:ANNUAL.ModeChanges:UniqueIndex:23:ALPHANUMERICSTUFF1234567ID:11:ACCT1234567OldValue:1:+NewValue:6:ANNUALChangeType:1:AChangeDate:20:6/03/2013 2:49:32 AM.
#0History:UniqueIndex:95:NOTTHESAME0987654|ALPHANUMERIC534|PRETEND349235|95CHARACTERSID:47:GNR44718500|PNR48CDQ704|PGP48090798|FGDS2345236SourceMode:26:ANNUAL|C-P-D|ANNUAL|ANNUALLoan:3:|||ModeChanges:UniqueIndex:95:00487SOMETHING4264500ORD|992581PROBABLY04ORD|0048SHOULD238BET|0095CHARS436PR638FGP07VDCID:47:GNR44718500|PNR48CDQ704|PGP48090798|FGDS2345236OldValue:7:+|+|+|+NewValue:26:ANNUAL|C-P-D|ANNUAL|ANNUALChangeType:7:A|A|A|AChangeDate:91:12/22/2013 11:53:11 PM|4/22/2013 11:53:11 PM|12/22/2013 11:53:11 PM|12/22/2013 11:53:11 PM.
The data is serialized table data of the form COLUMN_NAME:LENGTH_OF_ENTRY:DATA_FOR_COLUMN_ROW_1|DATA_FOR_COLUMN_ROW2|....NEXT_COLUMN_NAME...
Example of Function:
CREATE FUNCTION FUNCTION_THAT_UNSERIALIZES (#clob varchar(max),#colname varchar(max)) RETURNS #NewValue TABLE (ID INT,value varchar(max)) AS
BEGIN
DECLARE #colstart INT,#lenstart INT,#lenend INT,#collen VARCHAR(MAX),#lngth INT,#tmp VARCHAR(MAX), #rowid INT,#value VARCHAR(max),#next INT;
SELECT
#colstart = CHARINDEX(#colname,#tmp)+1,
#lenstart = CHARINDEX(':',#tmp,#colstart)+1,
#lenend = CHARINDEX(':',#tmp,#lenstart),
#collen = SUBSTRING(#tmp,#lenstart,#lenend - #lenstart),
#lngth = CAST (#collen AS INT),
#tmp = SUBSTRING(#tmp,#lenend,#lngth);
WHILE LEN(#tmp) > 0 BEGIN
SET #next = CHARINDEX('|',#tmp);
IF #next > 0 BEGIN
SET #value = SUBSTRING(#tmp,0,#next);
SET #tmp = SUBSTRING(#tmp,#next+1,LEN(#tmp) - #next);
END ELSE BEGIN
SET #value = #tmp;
SET #tmp = '';
END
INSERT INTO #NewValue VALUES(#rowid,#value)
SET #rowid = #rowid+1;
END
RETURN
Example Error
Msg 512, Level 16, State 1, Line 7
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Msg 4104, Level 16, State 1, Line 15
The multi-part identifier "SOURCE_TABLE.SOURCE_ID" could not be bound.
.. I think there might have been another one, but can't figure out how to reproduce it right this minute.
I think this might be the syntax you need to accomplish what I think you are trying to do.
CREATE VIEW UNSERIALIZED_TABLE_VIEW AS
SELECT
SOURCE_TABLE.ID SOURCE_ID,
a.*
FROM SOURCE_TABLE
CROSS APPLY FUNCTION_WHICH_UNSERIALIZES(DATA, #colname) a
I'm not certain what your #colname parameter should be; it is left out of your code in the question.

Subquery in an IN() clause causing error

I'm on SQL Server 2005 and I am getting an error which I am pretty sure should not be getting.
Msg 512, Level 16, State 1, Procedure spGetSavedSearchesByAdminUser, 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 am following the example# B on
this MSDN link.
My stored proc code is as follows. I can simplify it for the sake of this post if you request so:
ALTER PROCEDURE [dbo].[spGetSavedSearchesByAdminUser]
#strUserName varchar(50)
,#bitQuickSearch bit = 0
AS
BEGIN
SELECT [intSearchID] ,strSearchTypeCode ,[strSearchName]
FROM [tblAdminSearches]
WHERE
strUserName = #strUserName
AND
strSearchTypeCode
IN (
CASE #bitQuickSearch
WHEN 1 THEN 'Quick'
ELSE (SELECT strSearchTypeCode FROM tblAdvanceSearchTypes)
END
)
ORDER BY strSearchName
END
I have checked there is no datatype mismatch between the resultset from the subquery and the strSearchTypeCode the subquery result is compared with.
I see no reason why this should not work. If you have any clues then please let me know.
Try rearranging the query so that the boolean expression occurs inside the subselect, e.g.
ALTER PROCEDURE [dbo].[spGetSavedSearchesByAdminUser]
#strUserName varchar(50)
,#bitQuickSearch bit = 0
AS
BEGIN
SELECT [intSearchID] ,strSearchTypeCode ,[strSearchName]
FROM [tblAdminSearches]
WHERE
strUserName = #strUserName
AND
strSearchTypeCode
IN (SELECT strSearchTypeCode FROM tblAdvanceSearchTypes where #bitQuickSearch=0
UNION
SELECT 'Quick' AS strSearchTypeCode WHERE #bitQuickSearch=1)
ORDER BY strSearchName
END
I don't know that you can use the CASE statement inside of an IN clause like that. I'd suggest rewriting that bit to:
WHERE strUserName = #strUserName AND (
(#bitQuickSearch = 1 AND strSearchTypeCode = 'Quick')
OR
(strSearchTypeCode IN (SELECT strSearchTypeCode FROM tblAdvanceSearchTypes))
)
or, if you really like the style you got there:
WHERE strUserName = #strUserName
AND strSearchTypeCode IN (
SELECT CASE #bitQuickSearch WHEN 1 THEN 'Quick' ELSE strSearchTypeCode END
FROM tblAdvanceSearchTypes
)
In general, SQL should be smart to smart enough to optimize away the table if #bitQuickSearch = 1. But, I'd check the query plan just to be sure (trust, but verify).
It seems to me that this SELECT:
SELECT strSearchTypeCode FROM tblAdvanceSearchTypes
returns multiple rows, and that is your problem. You can rewrite it to be:
SELECT TOP 1 strSearchTypeCode FROM tblAdvanceSearchTypes

Resources