I am trying to get System Datetime for a column when a new row is inserted or updated into a table using stored Proc in MS SQL. How can I achieve it?
I have tried below code
CREATE PROCEDUCE test_Cl_INSERT
#SRC_ID int,
#CREATED_BY datatime
AS
BEGIN
INSERT into dbo.CL_Batch(SRC_ID, Created_BY)
VALUES(#SRC_ID, CURRENT_TIMESTAMP)
END
EXEC dbo.test_Cl_INSERT
#SRC_ID=44
ERROR : #CREATED_BY parameter missing
This will work:
CREATE PROCEDURE test_Cl_INSERT
#SRC_ID int
AS
BEGIN
INSERT into dbo.CL_Batch(SRC_ID, Created_BY)
VALUES(#SRC_ID, CURRENT_TIMESTAMP)
END
EXEC dbo.test_Cl_INSERT
#SRC_ID=44
Your procedure signature is:
CREATE PROCEDUCE test_Cl_INSERT
#SRC_ID int,
#CREATED_BY datatime
You attempt to execute as:
EXEC dbo.test_Cl_INSERT #SRC_ID=44
Do you see something missing? You should. Your procedure has 2 parameters but you provide only 1 when you attempt to execute it. That is your problem. As already noted, you don't use that paramter within the logic of the procedure so why does it exist at all?
You must execute your procedure like this:
EXEC dbo.test_Cl_INSERT #SRC_ID=44, #CREATED_BY = '20201124 12:49';
Notice I just assigned a random value to the parameter since it (the parameter) is not used within your procedure code. That solves the question you ask. However, you have more important issues to consider.
Related
I built a database application in Visual Studio. When I run, I get this error:
System.Data.SqlClient.SqlException: procedure sp_select_number_of_films has no parameters and arguments were supplied.
I know what the error means, but I am not sure how to fix it in my SQL code. I have tried a bunch of small tweaks, but I still get the same error.
Stored procedure:
CREATE PROCEDURE [dbo].[sp_select_number_of_films]
(#REC_ID_OUTPUT int OUTPUT)
AS
SELECT COUNT(*)
FROM Film.Title;
EXEC dbo.sp_select_number_of_films
GO
It should be called as:
DECLARE #sth INT;
Exec dbo.sp_select_number_of_films #sth OUTPUT;
But then inside stored procedure you need to assign output variable:
CREATE PROCEDURE [dbo].[sp_select_number_of_films]( #REC_ID_OUTPUT int OUTPUT)
AS SELECT #REC_ID_OUTPUT = COUNT(*)
FROM Film.Title;
And you should avoid naming stored procedures with "sp_" prefix.
I have edited my SQL code blocks to more accurately show what is going on
Say I have a simple stored procedure:
CREATE PROCEDURE [DBO].[FOO]
(#VARIABLE VARCHAR(500))
AS
BEGIN
SELECT AVG(BAR)
FROM MYTABLE
WHERE THING = #VARIABLE AND RTRIM(LTRIM(THING)) <> ''
END
When I call this stored procedure from my classic ASP page; which in this case would be with:
Set foo = Server.CreateObject("ADODB.RecordSet")
curCmd = "Foo 'MYVARIABLE'"
foo.Open curCmd, connectionString
I get this error (on the same line as the page opens the foo object):
Arithmetic overflow error converting varchar to data type numeric.
If I call the stored procedure manually in the terminal (IDE?); then it works fine.
Also if I recreate the stored procedure as the following:
CREATE PROCEDURE [DBO].[FOO]
(#VARIABLE VARCHAR(500))
AS
BEGIN
DECLARE #VARIABLE2 VARCHAR(500) = #VARIABLE
SELECT AVG(BAR)
FROM MYTABLE
WHERE THING = #VARIABLE2 AND RTRIM(LTRIM(THING)) <> ''
END
Then the stored procedure runs fine.
I have tried dropping and recreating the stored procedure (without using the re-declaration trick), but it does not fix the issue.
*As an aside; there is validation on the data being inserted into the table to ensure that only numbers (integers) are being entered for the THING field. The THING field can also be blank; hence the where clause.
I basically have two questions:
Why does re-declaring the same variable type with the same data fix the issue?
Is there a way I can fix my problem without using this silly "re-declaration" trick?
Thanks in advance for any help with this.
I think you can get the same error if you use begin/end:
CREATE PROCEDURE [DBO].[FOO] (
#VARIABLE VARCHAR(500)
)
AS
BEGIN
DECLARE #VARIABLE2 VARCHAR(500) = #VARIABLE;
SELECT AVG(BAR) FROM MYTABLE WHERE THING = #VARIABLE2;
END;
Then, both statements will be part of the stored procedure body and you can work on fixing the data so it will work.
Consider the following stored procedure:
ALTER PROCEDURE Administration.SetAndRetrieveNewPurchaseOrderNumber
#PurchaseOrderNumber INT OUTPUT
AS
BEGIN
SET NOCOUNT ON
UPDATE Administration.KeyNumbers
SET PurchaseOrderNumber += 1
WHERE RowId = 1
SET #PurchaseOrderNumber = (SELECT kn.PurchaseOrderNumber
FROM Administration.KeyNumbers kn
WHERE kn.RowId = 1)
END
GO
I can use this easily from within my application by simply executing the procedure and passing in by reference a suitably named parameter.
I now find myself wanting to execute the procedure listed above in another stored procedure. I tried the following, but it doesn't appear to work (either with or without the # symbol in the parameter part of the stored procedure being called;
DECLARE #PurchaseOrderNumber INT
EXEC Administration.SetAndRetrieveNewPurchaseOrderNumber(#PurchaseOrderNumber)
What is the correct way to do this, or in reality should there be a separate procedure for use in circumstances like this that only produces a scalar result?
You need to add the output keyword when passing in the parameter.
For example:
Declare #output int;
Exec storedproc(#parameter output)
The code is like this
INSERT INTO TABLE (VAL1,VAL2,VAL3) VALUES (X,Y,Z)
GetLastInsertID #tablename='TABLE'
GetLastInsertID is this Stored Procedure:
SELECT ##IDENTITY AS LastID FROM TABLE
How do I get the stored procedure to return the 'LastID' as requested in the Select ##IDENTITY statement above?
I get the following error:
Incorrect syntax near 'GetLastInsertId'.
...but this works fine when executed by itself:
GetLastInsertID #tablename='TABLE'
Okay, thanks i updated it to Scope_Identity(). But you're saying not to put it in a different SP, to put it in the same SP as the Insert?
Again, i still am getting an error when i combine an insert with this:
SELECT SCOPE_IDENTITY() AS LastID FROM TABLE
Here is the new error message:
There is already an object named 'TABLE' in the database.
It's a bad idea to separate this into a stored procedure at all, because a stored procedure creates a new scope/context. That leaves you open to grabbing the wrong ID number. If one user in a session inserts many rows together, you might get the wrong result.
Instead, you almost always want the scope_identity() function, and you want to call it in the same context as the statement that created the new record.
In the first place you do not ever want to use ##identity as it can break if someone adds a trigger.
What you want to use is the OUTPUT clause or scope_identity. See Books online for examples of how to use OUTPUT.
your error is in your failure to include the EXECUTE command, try this:
INSERT INTO TABLE (VAL1,VAL2,VAL3) VALUES (X,Y,Z)
EXEC GetLastInsertID #tablename='TABLE'
the EXEC is assumed when you attempt to run a procedure with no other commands, however when you include the INSERT it makes the EXEC required.
Now, you really need to determine if what you are trying to do is a good design.
try this:
DECLARE #LastId int
INSERT INTO TABLE (VAL1,VAL2,VAL3) VALUES (X,Y,Z)
SELECT #LastID=SCOPE_IDENTITY()
Here is my sample code that does this. (But the stored proc doesn't add any value.)
--First create a test table.
create table test
(id int identity,
name varchar(30))
go
--A stored proc that returns the scope_identity()
create proc dbo.spTest
as
insert into test(name)
values ('test')
return scope_identity()
go
-- Sample call
declare #newId int
exec #newId = spTest
print #newId
I have following trigger. On Insertion of a new row, the Stored Procedure is unable to get the parameter value of variable #ItemID. I am trying to pass the value of ItemID Column of newly inserted Row to the stored procedure CalculateCurrentStock
ALTER TRIGGER UpdateCurrentStock
ON StockIn
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
EXEC CalculateCurrentStock (SELECT ItemID From INSERTED)
END
The error text reads
Procedure or function 'CalculateCurrentStock' expects parameter
'#ItemID', which was not supplied. The statement has been terminated.
Thank you for help.
EDIT: Answer
I have altered the trigger as per Derek Kromm's and KM's suggestion
ALTER TRIGGER UpdateCurrentStock
ON StockIn
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #CSV varchar(max)
SELECT #CSV=ISNULL(#CSV+',','')+ItemID From INSERTED
EXEC CalculateCurrentStock #CSV
END
Thanks for help :)
Edit: As Martin pointed out, you can pass a table-valued parameter if you're using SQL Server 2008. If you're using 2005 or prior, you can't do that. KM suggests using a comma-delimited value in this case, which I personally disagree with.
In reality, you should probably copy the stored procedure logic directly into the trigger and avoid the whole mess altogether.
I'd personally poke out my eye before using a cursor, especially when you can pass in a set of values (table values parameter, or CSV) all at one time in a single procedure call.
if you are running SQL Server 2008 you can create your procedure using a Table-Valued Parameters and should be able to pass in the INSERTED table.
If your are using SQL Server 2005 you can create a comma separated value (csv) list of values within a varchar(max) variable and pass that in to your procedure.
EDIT, here is how to pass in a CSV
ALTER TRIGGER UpdateCurrentStock
ON StockIn
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #CSV varchar(max)
SELECT #CSV=ISNULL(#CSV+',','')+ItemID From INSERTED
EXEC CalculateCurrentStock #CSV
END
now, within you'll need to split apart the #CSV values, so look here: Pass a list-structure as an argument to a stored procedure