I have a following stored procedure
CREATE PROCEDURE [dbo].[InsertCategory]
#Name nvarchar(100)
AS
BEGIN
INSERT INTO [dbo].[Category]([Name])
OUTPUT INSERTED.CategoryId, INSERTED.[Timestamp]
VALUES (#Name)
END
And I call it like this:
EXEC [dbo].[InsertCategory] #Name= #Name
I would like to know what the id of inserted Category is (it is output in insert statement). It is written to the output, but I can't figure out how to assign it to a variable without modifying stored procedure. In C# I can use command.ExecuteReader and I get it, but I do not know how to get it in SQL Server.
I also cannot use SCOPE_IDENTITY as we have our own system of generating ids.
Try this:
-- count use a temp table as well
-- syntax: CREATE TABLE #t(CategoryId int,[Timestamp] datetime)
DECLARE #t table(CategoryId int,[Timestamp] datetime)
INSERT #t(CategoryId, [TimeStamp])
EXEC [dbo].[InsertCategory] #Name= #Name
SELECT CategoryId, [TimeStamp]
FROM #t
You can Declare a table and insert output into it.
CREATE PROCEDURE [dbo].[InsertCategory]
#Name nvarchar(100)
AS
BEGIN
DECLARE #Result AS TABLE (
CategoryId int,
TimeStamp varchar(50)
)
INSERT INTO [dbo].[Category]([Name])
OUTPUT INSERTED.CategoryId, INSERTED.[Timestamp]
INTO #Result(CategoryId, TimeStamp)
VALUES (#Name)
SElect * from #Result
END
Related
declare #temp table
(
ItemID varchar(100),
)
INSERT INTO #temp (ItemID, Qt)
EXEC A 'LA'
I want to then take the temp table results in field1 (will show field1 and field2) and loop those results using stored procedure B.
Figured I'd provide an example (I was 99% sure my comment was correct but thought I'd double-check.
CREATE PROC dbo.A #x varchar(10) AS SELECT #x FROM (VALUES (1),(1),(1))x(x);
CREATE PROC dbo.B AS SELECT * FROM ##xx;
IF object_id('tempdb..##xx') IS NOT NULL DROP TABLE ##xx;
CREATE TABLE ##xx (col1 varchar(10));
INSERT ##xx EXEC dbo.A 'hi';
EXEC dbo.B;
Results:
col1
------
hi
hi
hi
You could create a User-Defined Table Type, declare a variable as that type (instead of declaring a table variable) and send that over to a procedure which is expecting that type - as a READONLY.
For example:
CREATE TYPE SomeTableType AS TABLE(
[Id] INT,
[Val] VARCHAR(10)
)
Create a procedure that takes this type as a READONLY parameter:
CREATE PROCEDURE p_some_procedure_name
#table SomeTableType READONLY
AS
SELECT * FROM #table;
Now you can declare an instance of your type anywhere (say another procedure), populate it with data and call p_some_procedure_name with it:
DECLARE #temp_table SomeTableType;
INSERT #temp_table(Id, Val) VALUES (1, 'First'), (2, 'Second');
EXEC p_some_procedure_name #temp_table;
If possible (which is often the case), avoid looping.
Initially, I'll be storing all columns of source table to single variable using stored procedure(SP1). This SP1 is called inside SP2 and that variable is inserted into destination table.
I know the approach but stuck in implementing it.
-- SP1
Create procedure insert_data
AS
Declare #data nvarchar(60)
Begin
EXEC get
--Here i have to insert
END
Go
--SP2
Create procedure get_column
AS
Declare
#e_id int , #e_name nvarchar(20) , #d_id int,#res nvarchar(50)
Begin
SET #e_id =(select Emp_ID from Dim_Employee where Emp_Name='Cathy');
SET #e_name =(select Emp_Name from Dim_Employee where emp_id=101);
SET #d_id =(select Dept_ID from Dim_Employee where emp_name='Cathy');
SET #res ='#e_id , #e_name , #d_id';
return #res
END
Go
if you already have destination table:
insert into DestTbl(emp_id, dept_id, ...)
select emp_id, dept_id, ...
from Dim_Employee d
where ...
if you dont and wish to create it
select emp_id, dept_id, ...
into DestTbl
from Dim_Employee d
where ...
if you still want to use variables
insert into DestTbl(emp_id, dept_id)
values (#emp_id, #dept_id, ...)
is this what you're asking for?
INSERT statement on msdn:
https://technet.microsoft.com/en-us/library/ms174335.aspx
I have two stored procedures as follows:
create stored procedure p1
as
select * from table1 where datediff(day, table1.[date], getdate())
create stored procedure p2
as
declare #t1 table(
ref varchar(20)
)
insert into #t1 select * from table1 where ref = 'some ref'
declare #t2 table(
fname varchar(20),
lname varchar(20),
email varchar(1000)
)
declare #len int = (select count(ref) from #t1)
while #len > 0
begin
declare #value varchar(20) = (select top 1 ref from #t1)
insert into #t2 select * from table2 where ref = #ref
delete from #t1
where ref = #value
set #len = (select count(ref) from #t1)
end
select * from #t2
Java code
....
String query = "Execute [p2]";
try(CallableStatement cstmt = conn.prepareCall(query);
ResultSet rs = cstmt.executeQuery()){
... some code
}
The table variable #t1 hold select result from a table 'table1'
The variable #len hold the number of rows in #t1
Using #len > 0 as condition in while loop, I want to select records from another table 'table2' the table variable #t2 hold the select records from 'table2'
The delete statement removes value from #t1
#len set to new number of rows in #t1
the last statement return all the records store in #t2
The first procedure works fine, but the second procedure works only in SQL Server.
I get this an error message in my java application
statement did not return a resultset
I want this to return a result set with the select statement I have at the
end of the query.
Please is there a way around this?
Your [p2] stored procedure needs to include SET NOCOUNT ON right at the beginning to suppress the "n rows affected" counts so JDBC doesn't get confused as to what it should put into the ResultSet:
CREATE PROCEDURE p2
AS
SET NOCOUNT ON;
declare #t1 table(
ref varchar(20)
)
-- ... and so on
For more information on SET NOCOUNT see
SET NOCOUNT (Transact-SQL)
For more information on precisely what gets returned from a stored procedure call, see
How to get everything back from a stored procedure using JDBC
use method "execute" instead of "executeQuery".
I created a following test stored procedure.
CREATE PROCEDURE [dbo].[TestA]
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #MyTableA (ID INT, Name VARCHAR(255))
CREATE TABLE #MyTableB (ID INT, Name VARCHAR(255))
..............
EXEC TestB;
SELECT * FROM #MyTableB;
END
The TestB stored procedure returns a result set. But I need to call it. According to this stored procedure, the two result sets are returned. But I need to return one. How can I do this? Thanks.
Try this :-
CREATE PROCEDURE [dbo].[TestB]
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #MyTableA (ID INT, Name VARCHAR(255))
CREATE TABLE #MyTableB (ID INT, Name VARCHAR(255))
.............
INSERT INTO #MyTableA
exec TestA
DROP TABLE #MyTableA
SELECT * FROM #MyTableB;
END
I am trying to find the identity value of an inserted record inserted by exec(#Sql), but it seems that exec() excutes in a different scope.
/*
create table [dbo].[__Test](
[id] [int] IDENTITY(1,1) NOT NULL,
[description] [varchar](100) NULL
) ON [PRIMARY]
GO
*/
declare #Sql varchar(512)
set #Sql = 'insert into [dbo].[__Test] ([description]) values (''Some text'')'
exec (#Sql)
select
##IDENTITY as [##IDENTITY],
scope_identity() as [scope_identity],
ident_current('__Test') as [ident_current]
/*
if exists(select * from sys.objects where object_id = object_id('[dbo].[__Test]') and type='U')
drop table [dbo].[__Test]
GO
*/
returns:
##IDENTITY scope_identity ident_current
---------- -------------- -------------
14 NULL 14
and if there is a trigger on __Test, returns:
##IDENTITY scope_identity ident_current
---------- -------------- -------------
6 NULL 14
So ##IDENTITY could be a trigger insert, the execution is not in scope and ident_current() could be from another user.
Is there any way of reliably finding the identity value from an insert made by exec()?
yes, by using sp_executesql:
DECLARE #nSQL NVARCHAR(500)
DECLARE #NewID INTEGER
SET #nSQL = 'INSERT MyTable (MyField) VALUES (123) SELECT #NewID = SCOPE_IDENTITY()'
EXECUTE sp_executesql #nSQL, N'#NewID INTEGER OUTPUT', #NewId OUTPUT
--#NewId now contains the ID
The advantage of sp_executesql is you can parameterise the SQL statement being executed, so you don't have to concentenate values into a string to then be executed.
I had the same problem, but instead of using sp_executesql I've used a more native solution which also works for other data you want to bring outside.
You can pass variables from inside the EXEC to the calling scope like this:
DECLARE #Result AS Table (Value int)
INSERT INTO #Result EXEC('INSERT INTO MyTable(Fields) ''Value''; SELECT ##IDENTITY')
SELECT Value FROM #Result