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.
Related
I wrote some SQL statements that work for updating a single customer. I have to update all the customers when this code gets pushed out.
Right now the customer ID is hardcoded and the SQL statements insert one record based on that ID. Prototype works, now I want to do like 10,000 inserts for all of the customers using the same algorithm.
DECLARE #customerID BIGINT = 47636;
DECLARE #limitFourAdjustment MONEY;
DECLARE #appliesToDateTime DATETIME2(7) = SYSUTCDATETIME();
DECLARE #dp_y INT = DATEPART(YEAR, #appliesToDateTime);
DECLARE #dp_m INT = DATEPART(MONTH, #appliesToDateTime);
DECLARE #dp_w INT = DATEPART(WEEK, #appliesToDateTime);
DECLARE #dp_d INT = DATEPART(DAY, #appliesToDateTime);
DECLARE #dp_h INT = DATEPART(HOUR, #appliesToDateTime);
DECLARE #d_h DATETIME2(7) = DATEADD(HOUR, DATEDIFF(HOUR, 0, #appliesToDateTime), 0);
SELECT
#limitFourAdjustment = -COALESCE(SUM(COALESCE(Amount, 0)), 0)
FROM
[dbo].Transactions
WHERE
CustomerID = #customerID AND
IsSystemVoid = 0 AND
TransactionTypeID IN (SELECT ID FROM TransactionTypes WHERE TransactionTypeGroupID = 3)
INSERT INTO dbo.CustomerAccounts_TransactionSummation (CustomerID, LimitTypeID, Y, M, W, D, H, YMDH, Amount)
VALUES (#customerID, 4, #dp_y, #dp_m, #dp_w, #dp_d, #dp_h, #d_h, #limitFourAdjustment);
I tried adding a while loop, seems like not the fastest solution. Maybe collect the ID's first and then feed it to through the loop? My first attempt below doesn't work because I just get the last customer ID, not a unique one every time.
SELECT #numberOfCustomers = COUNT(*)
FROM dbo.Customers
WHILE(#numberOfCustomers > 0)
BEGIN
SELECT #customerID = ID FROM dbo.Customers
OTHER LOGIC FROM ABOVE
SET #numberOfCustomers = #numberOfCustomers - 1;
END
So the question is, how to run these SQL statements (first code block) on every customer's ID?
The key to working with databases is getting your mind around set based operations as opposed to procedural operations. Databases are designed to operate naturally on sets of data at a time, but you have to change how you think about the problem to one where you are manipulating the entire set of data as opposed to one record at a time.
So here is the SQL which I think carry out your complete update in one hit:
INSERT INTO dbo.CustomerAccounts_TransactionSummation (CustomerID, LimitTypeID, Y, M, W, D, H, YMDH, Amount)
SELECT
id
, 4
, #dp_y
, #dp_m
, #dp_w
, #dp_d
, #dp_h
, #d_h
, -COALESCE(SUM(COALESCE(Amount, 0)), 0) limitFourAdjustment
FROM [dbo].Transactions
WHERE IsSystemVoid = 0
and TransactionTypeID IN (SELECT ID FROM TransactionTypes WHERE TransactionTypeGroupID = 3)
--and CustomerID = #customerID
Note that the insert can be combined directly with a select as opposed to using values.
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;
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.
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)
I am trying to update multiple rows in one table, based on a select statement on another table.
This is my query:
UPDATE dbo.[user_message_content]
SET [status] = 1
WHERE [message_id] = (SELECT [message_id] FROM dbo.[user_message] WHERE [receiver_id] = #userID)
AND [status] = 0
This select statement may return multiple rows, which leads me to this error:
Msg 512, Level 16, State 1, Procedure usp_profileUserMessageMarkAsRead, Line 11
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
What is the correct way to achieve what I need?
Thanks very much
If you want to update all those records, change the = to IN:
UPDATE dbo.[user_message_content]
SET [status] = 1
WHERE [message_id] IN
( SELECT [message_id] FROM dbo.[user_message] WHERE [receiver_id] = #userID )
AND [status] = 0
You can also use UPDATE with FROM clause http://msdn.microsoft.com/en-us/library/aa260662(SQL.80).aspx.
USE tempdb;
GO
create table #user_message_content([status] int, message_id int)
create table #user_message (message_id int,receiver_id int)
declare #UserID int
UPDATE mc
SET mc.[status] = 1
FROM #user_message_content mc join #user_message m on mc.message_id = m.message_id
WHERE m.receiver_id = #userID
AND mc.[status]=0;
drop table #user_message_content
drop table #user_message
I think you need to use a join to do this
USE dbo; // Sets the current database to dbo, I did this for readability
UPDATE user_message_content join user_message on user_message_content.message_id = user_message.message_id
SET user_message_content.status = 1
WHERE user_message.receiver_id = #userID;