I have created a stored procedure that returns the id of last inserted row of a table based on one condition.
Condition is such that if the row being inserted already exists then it takes identity column of the row otherwise it inserts a new row into the table.
To do this, I have written the following code in a stored procedure
ALTER PROCEDURE [dbo].[Test_Procedure]
#description nvarchar(max)
AS
BEGIN
DECLARE #tempId int;
SELECT CommentId
INTO tempId
FROM TestTable
WHERE description = #description;
IF #tempId IS NULL
BEGIN
INSERT INTO TestTable
VALUES (#description);
SELECT scope_identity();
END
ELSE
BEGIN
SELECT #tempId FROM dual;
END
DROP TABLE tempId;
END
When I run the above stored procedure, first time it ran successfully and then on wards it started throwing the following error message
Msg 2714, Level 16, State 6, Procedure Test_Procedure, Line 15
There is already an object named 'tempId' in the database.
The bit I'm not understanding is tempId is used as a variable not as a table. I have seen people with the similar problem but in their case they used temporary tables
I really appreciate your help in resolving the above issue.
Try this syntax for setting your variable.
SELECT #tempId = CommentId from TestTable where description = #description;
Currently your 'select into' is creating a table 'tempId' on the database.
Related
I had written and successfully created a stored procedure by the query
CREATE PROCEDURE [dbo].[Table_Load]
AS
BEGIN
SET NOCOUNT ON
DECLARE #Row_Count_Inserted BIGINT
DROP TABLE IF EXISTS DBB.dbo.Table;
SELECT *
INTO DBB.dbo.Table
FROM
(SELECT *
FROM DBB.dbo.customer_table) y
SET #Row_Count_Inserted = ##RowCount
SELECT #Row_Count_Inserted Row_Count_Inserted
END
This shows that the stored procedure is created and is present in the database. But when I query the table 'Table' using
SELECT * FROM DBB.dbo.Table
I get an error
Invalid object name
How can I solve this issue? I have refreshed the database as well but it does not work.
Here is your procedure greatly simplified to remove a lot of extra code. Assuming you have the table customer_table this will work just fine.
CREATE or alter PROCEDURE [dbo].[Table_Load] As
Begin
SET NOCOUNT ON
drop table If Exists dbo.MyTable;
Select *
into MyTable
from customer_table
select Row_Count_Inserted = ##RowCount
End
GO
exec Table_Load
GO
select * from MyTable
I have created a SQL Server stored procedure which contains insert and update statements and log table. When I execute the stored procedure locally using
EXEC stored_procedure_name param1
it works perfectly fine and logs entry is inserted into the log table; but when the same stored procedure is called from another server using the same SQL Server user, the stored procedure is called and correct output/response is going to calling server but insert and update statements are not executed and no logs are inserted.
Again, when I call the stored procedure locally, everything works. When I checked the entries in log table (with Id column as identity(1,1)), there are 2 entries with id 1 and 3.
I think entry with Id = 2 is inserted and then rollback as it called from another server.
I don't understand the different behavior. Please help.
Thanks in advance
ALTER PROCEDURE [dbo].[temp_procedure]
(#aid VARCHAR(MAX))
AS
BEGIN
SET NOCOUNT ON;
DECLARE #RETURN_CODE INT = -2;
DECLARE #RETURN_MESSAGE VARCHAR(MAX) = 'ENTITY NOT FOUND';
-- Check IF exist and Update
IF EXISTS (SELECT 1 FROM temp WHERE c = #aid)
BEGIN
UPDATE temp
SET a = 0, b = 0,
WHERE c = #aid;
SET #RETURN_CODE = 0;
SET #RETURN_MESSAGE = 'SUCCESS';
END
-- Log action and result in logging table for particular a_id
-- also has id column as identity
INSERT INTO [dbo].[Logs] ([A_Id], [Created_Date], [Return_Code], [Return_Message])
VALUES (#aid, GETDATE(), #RETURN_CODE, #RETURN_MESSAGE)
SELECT #RETURN_CODE AS 'RETURN_CODE', #RETURN_MESSAGE AS 'RETURN_MESSAGE';
END
I have a transaction that calls a stored procedure which creates a temp table. I need to be able to access this temp table outside of the stored procedure after it has been ran. Note: for what I am trying to do, I cannot use global temp tables.
Example:
Here is an example of the stored procedure:
CREATE PROCEDURE [dbo].[GetChangeID]()
AS
BEGIN
IF OBJECT_ID('tempdb..#CurrentChangeID') IS NOT NULL
DROP TABLE #CurrentChangeID
SELECT '00000000-0000-0000-0000-000000000000' AS ChangeID INTO #CurrentChangeID
END
GO
Here is an example of the transaction:
BEGIN TRANSACTION
DECLARE #changeID uniqueidentifier
EXEC dbo.GetChangeID
DECLARE #test uniqueidentifier
SET #test = (SELECT ChangeID FROM #CurrentChangeID)
COMMIT TRANSACTION
GO
The issue is that it cannot find a table named #CurrentChangeID.
How can I make it to where it can see this table without declaring it as a global temp table such as ##CurrentChangeID?
------UPDATE------
So let me give more context to my question because that was just a simplified example. So what I am ultimately trying to do is this: 1. Begin Transaction 2. Call stored procedure that generates the GUID 3. Then update row in a given view that has a trigger. 4. Within that trigger get the GUID that was generated within the sp. 5. Commit.
First of all you can't get access to local temp table defined in SP outside stored procedure. It will always be out of scope.
Second you probalbly don't even need temp table. In your example:
SET #test = (SELECT ChangeID FROM #CurrentChangeID)
it looks like you want only one value.
I propose to use output parameter.
CREATE PROCEDURE [dbo].[GetChangeID](
#test UNIQUEIDENTIFIER OUTPUT
)
AS
BEGIN
-- ...
SET #test = '00000000-0000-0000-0000-000000000000';
END;
And call:
DECLARE #changeID uniqueidentifier
EXEC dbo.GetChangeID #chaneId OUTPUT;
SELECT #changeId;
Thank you lad2025 and Dan Guzman for your input. The way I was originally trying to do this was definitely incorrect.
I did, however, figure out a way to accomplish this task.
Modified Stored Procedure:
CREATE PROCEDURE [dbo].[GetChangeID]()
AS
BEGIN
DECLARE #ChangeID uniqueidentifier
...
Code that generates the uniqueidentifier, #ChangeID.
...
--This can be seen within the context of this batch.
SET CONTEXT_INFO #ChangeID
END
GO
Then anywhere within this transaction that you would like to access the changeID, you just have to use the following query:
SELECT CONTEXT_INFO as changeID
FROM sys.dm_exec_requests
WHERE session_id = ##SPID AND request_id = CURRENT_REQUEST_ID()
I have a stored procedure that contains the following logic:
Starts transaction scope using BEGIN TRANS A
Calls a second stored procedure where a record in Table1 is updated
Control returns to the original stored procedure where a SELECT is run against Table1
Commit transaction using COMMIT TRANS A
For some reason, that SELECT in step 3 is always returning the data values before the table was updated. I need the updated values from Step 2, that haven't been committed, to be returned by my SELECT.
How would I go about selecting the dirty/uncommitted data from Table1?
The scenarios described sounds a little off to me. You can begin a transaction and then execute a procedure. The data affected by that procedure is part of the transaction. This is painless to test and demonstrate.
create table TransactionDemo
(
SomeValue varchar(50)
)
insert TransactionDemo
select 'This is the original data.'
GO
create procedure TransactionDemoUpdate as
set nocount on;
update TransactionDemo
set SomeValue = 'This is updated data.'
GO
begin transaction
select * from TransactionDemo --data prior to calling procedure
exec TransactionDemoUpdate --will update the data
select * from TransactionDemo --see the values have changed
rollback transaction
select * from TransactionDemo --after the rollback they are the original values again.
I have a stored procedure which is returning a result in an xml #Data output parameter
To assign data in xml code is
SELECT #data= (
SELECT DISTINCT
CONVERT(varchar(2),u.USER_SOURCE ) + '~' +
CONVERT(varchar(20), u.[USER_ID]) + '-' +
CONVERT(varchar(10), u.DEALER_ID) as USER_DEALER_ID
FROM #users u FOR XML RAW('users'))
When I exec the procedure in SQL Server Mgmt Studio, I can see the result OK.
This procedure is been called from another procedure, and that parent procedure is used in SSRS.
In SSRS I am getting error
Query execution failed for dataset 'DataSet1'. Invalid column name
'USER_SOURCE'. Invalid column name 'USER_ID'. Invalid column name
'DEALER_ID'.
Could you please help?
Thanks,
Chetan
Here's a script which I think reproduces a problem identical to yours:
CREATE PROCEDURE TestTmpTable
#value varchar(20)
AS
BEGIN
CREATE TABLE #test (id int IDENTITY, value varchar(20));
INSERT INTO #test (value) VALUES (#value)
SELECT * FROM #test;
DROP TABLE #test;
END
GO
CREATE TABLE #test (id int IDENTITY, value2 varchar(20));
EXEC TestTmpTable 'some text';
SELECT * FROM #test;
DROP TABLE #test;
GO
DROP PROCEDURE TestTmpTable
As you can see, there are two #test tables here, one is created in the stored procedure, the other one in the batch that invokes the stored procedure. They have different structures: one has a column named value, the other a column named value2. If you run the script, you'll see this error:
Msg 207, Level 16, State 1, Procedure TestTmpTable, Line 6
Invalid column name 'value'.
I can't point you to a relevant documentation article at the moment, but to me it is evident enough that some preliminary name checking is taking place immediately before the execution of the SP. At that stage, a discrepancy between the column names referenced in the stored procedure and those actually present in the already existing table is revealed, which renders the execution impossible.
If you change value2 to value, the script will work without any problem, and there will be two row sets in the output, one with the 'some text' value, the other empty. And of course the script will work if you remove all parts related to the external #test table.
So, check the places where your procedure is called to see if any other #users table can be existing by that moment, and if so, amend the issue according to your situation.