I have the following stored procedure, it inserts a record into Table2, and updates id column in Table1. The id in Table1 comes from the serial key in Table2.
I used SCOPE_IDENTITY() to get the latest assigned serial key in the scope.
However, when I execute the procedure and #flag = 1, no record is selected.
I know WHERE id = #id is something wrong because when I comment out the where clause, it works.
DECLARE #id INT
SELECT id, * INTO #t FROM Table1
IF #flag = 1
BEGIN
INSERT INTO Table2 (col1, col2)
VALUES ('value', 'value2')
SET #id = SCOPE_IDENTITY()
UPDATE Table1
SET id = #id
SELECT *
FROM #t
WHERE id = #id ---this is the problem!!
END
ELSE
BEGIN
SELECT * FROM #t
END
What is wrong with this?
Here's the issue, your IDs are not yet available in your #t table. Populate this table after you update your ID in Table1.
BEGIN
DECLARE #id INT
IF #flag = 1
BEGIN
Insert Table2(col1,col2)
VALUES ('value', 'value2')
SET #id = SCOPE_IDENTITY();
UPDATE Table1
SET id = #id;
SELECT id, * INTO #t From Table1; -- This should be its position.
SELECT *
FROM #t
WHERE id = #id
END
ELSE
BEGIN
SELECT id, * FROM Table1
END
END
Related
I am having six select queries with different where conditions if first select query returns null it should check the next select query and follows. what is the best approach to follow for writing it as stored procedure in SQL server.
You can use ##rowcount
DECLARE #OperatorID INT = 4, #CurrentCalendarView VARCHAR(50) = 'month';
declare #t table (operatorID int, CurrentCalendarView varchar(50));
insert into #t values (2, 'year');
select operatorID - 1, CurrentCalendarView from #t where 1 = 2
if (##ROWCOUNT = 0)
begin
select operatorID + 1, CurrentCalendarView from #t where 1 = 1
end
If I understand your question correctly then you can achieve this like below sample. You can go in this way.
if NOT EXISTS (SELECT TOP(1) 'x' FROM table WHERE id =#myId)
BEGIN
IF NOT EXISTS (SELECT TOP(1) 'x' FROM table2 WHERE id = #myId2)
BEGIN
IF NOT EXISTS (SELECT TOP(1) 'x' FROM table 3 WHERE id = #myID3)
BEGIN
END
END
END
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 have some SQL within a stored procedure where I am updating a table based on another SELECT statement from a temp table (code below).
SET NOCOUNT ON
DECLARE #RowCount int
UPDATE TABLEX SET
TRA = ISNULL (ir.DcTra, DCBASIC.TRA),
TRD = ISNULL(CAST(NULLIF(REPLACE(ir.DcTRD, '-', ''), '') AS datetime), DCBASIC.TRD),
LSINC = ISNULL(ir.DcLsInc, DCBASIC.LSINC),
REVSWOVR = ISNULL(ir.DcRevswovr, DCBASIC.REVSWOVR) FROM #TempData ir WHERE TABLEX.MEMBNO = ir.IntMembNo
SET #RowCount = ##ROWCOUNT
The #RowCount variable is being set to 1.
The SELECT of the #TempData table returns no rows and no rows in the TABLEX table are updated (or even exist) with the MembNo (I have added SELECT statements within the sp to debug and they confirm this)
Why is #RowCount being set to 1?
Here is an explanation:
Statements that make a simple assignment always set the ##ROWCOUNT value to 1.
More information you can find here:
##ROWCOUNT
My example:
CREATE DATABASE FirstDB
GO
USE FirstDB;
GO
CREATE TABLE Person (
personId INT IDENTITY PRIMARY KEY,
firstName varchar(20) ,
lastName varchar(20) ,
age int
)
INSERT INTO dbo.Person (firstName, lastName, age)
VALUES ('Nick', 'Smith', 30),
('Jack', 'South', 25),
('Garry', 'Perth', 20)
CREATE TABLE PersonAge (
personAgeId INT IDENTITY PRIMARY KEY ,
personId INT ,
newAge varchar(10)
)
INSERT INTO dbo.PersonAge(personId, newAge)
VALUES (1, 60),
(2, 65),
(3, 70)
ALTER TABLE dbo.PersonAge
ADD CONSTRAINT FK_PersonAgePerson FOREIGN KEY (personId)
REFERENCES dbo.Person (personId)
And then example of query:
USE FirstDB;
GO
SET NOCOUNT ON;
DECLARE #row int;
UPDATE Person
SET age = 40
FROM dbo.Person as p join dbo.PersonAge as p1
ON p.personId = p1.personId
WHERE p.age = 60
SET #row = ##ROWCOUNT
SELECT #row
I create an UPDATE query where none of rows will be affected.
At the end #row consist 0 value.
Here is another example, using INSERT and DELETE--
DECLARE #deletedRows INT = 0;
SELECT #deletedRows = ##ROWCOUNT; --no previous DML statement
SELECT #deletedRows; --##ROWCOUNT = 1 for a simple assignment
GO
DROP TABLE IF EXISTS #Test;
GO
CREATE TABLE #Test (ID INT IDENTITY, CurrentDate DATETIME DEFAULT GETDATE());
GO
INSERT #Test DEFAULT VALUES; --INSERT a single row
DECLARE #deletedRows INT = ##ROWCOUNT; --##ROWCOUNT = 1
SELECT #deletedRows;
GO
DELETE FROM #Test WHERE 1=2; --no rows deleted
DECLARE #deletedRows INT = ##ROWCOUNT; --##ROWCOUNT = 0
SELECT #deletedRows;
GO
DELETE TOP (1) t FROM #Test t WHERE 1=1; --1 row deleted
DECLARE #deletedRows INT = ##ROWCOUNT; --##ROWCOUNT = 1
SELECT #deletedRows;
GO
DELETE TOP (1) t FROM #Test t WHERE 1=1; --no rows left to delete
DECLARE #deletedRows INT = ##ROWCOUNT; --##ROWCOUNT = 0
SELECT #deletedRows;
GO
I am writing a store procedure in T-SQL which inserts a row to the table, based on parameters
#UserName ,#CompanyName ,#RestName,#Desc
INSERT INTO Orders(UserId,CompanyId,RestId)
SELECT UserNames.Id,CompanyNames.Id,RestNames.Id FROM UserNames,CompanyNames,RestNames
WHERE
UserNames.Name = #UserName AND
CompanyNames.Name = #CompanyName AND
RestNames.Name = #RestName
Besides the insert to the 3 columns above,I also want to insert the #Desc value.
I tried :
INSERT INTO Orders(UserId,CompanyId,RestId,Desc)
VALUES(
(SELECT UserNames.Id,CompanyNames.Id,RestNames.Id FROM UserNames,CompanyNames,RestNames
WHERE
UserNames.Name = #UserName AND
CompanyNames.Name = #CompanyName AND
RestNames.Name = #RestName),#Desc)
Only one expression can be specified in the select list when the subquery is not introduced with EXISTSt-
It doesn`t work giving the following error:
#UserName ,#CompanyName ,#RestName,#Desc
INSERT INTO Orders(UserId,CompanyId,RestId, Desc_Column)
SELECT UserNames.Id,CompanyNames.Id,RestNames.Id , #Desc --<-- Just SELECT that variable
FROM UserNames,CompanyNames,RestNames -- in your select statement.
WHERE UserNames.Name = #UserName
AND CompanyNames.Name = #CompanyName
AND RestNames.Name = #RestName
Retrieve ID Values Inserted
DECLARE #t TABLE (ID INT); --<-- Declare a table variable
INSERT INTO Orders(UserId,CompanyId,RestId, Desc_Column)
OUTPUT Inserted.ID INTO #t --<-- use OUTPUT, get values from INSERTED Table
SELECT UserNames.Id,CompanyNames.Id,RestNames.Id , #Desc --and insert them into your table variable
FROM UserNames,CompanyNames,RestNames
WHERE UserNames.Name = #UserName
AND CompanyNames.Name = #CompanyName
AND RestNames.Name = #RestName
/*At last just simply select from that table variable to get the inserted IDs*/
SELECT * FROM #t
I have a requirement to insert multiple rows into table1 and at the same time insert a row into table2 with a pkID from table1 and a value that comes from a SP parameter.
I created a stored procedure that performs a batch insert with a table valued parameter which contains the rows to be inserted into table1. But I have a problem with inserting the row into table2 with the corresponding Id (identity) from table1, along with parameter value that I have passed.
Is there anyone who implemented this, or what is the good solution for this?
CREATE PROCEDURE [dbo].[oSP_TV_Insert]
#uID int
,#IsActive int
,#Type int -- i need to insert this in table 2
,#dTableGroup table1 READONLY -- this one is a table valued
AS
DECLARE #SQL varchar(2000)
DECLARE #table1Id int
BEGIN
INSERT INTO dbo.table1
(uID
,Name
,Contact
,Address
,City
,State
,Zip
,Phone
,Active)
SELECT
#uID
,Name
,Contact
,Address
,City
,State
,Zip
,Phone
,Active
,#G_Active
FROM #dTableGroup
--the above query will perform batch insert using the records from dTableGroup which is table valued
SET #table1ID = SCOPE_IDENTITY()
-- this below will perform inserting records to table2 with every Id inserted in table1.
Insert into table2(#table1ID , #type)
You need to temporarily store the inserted identity values and then create a second INSERT statement - using the OUTPUT clause.
Something like:
-- declare table variable to hold the ID's that are being inserted
DECLARE #InsertedIDs TABLE (ID INT)
-- insert values into table1 - output the inserted ID's into #InsertedIDs
INSERT INTO dbo.table1(ID, Name, Contact, Address, City, State, Zip, Phone, Active)
OUTPUT INSERTED.ID INTO #InsertedIDs
SELECT
#ID, Name, Contact, Address, City, State, Zip, Phone, Active, #G_Active
FROM #dTableGroup
and then you can have your second INSERT statement:
INSERT INTO dbo.table2(Table1ID, Type)
SELECT ID, #type FROM #InsertedIDs
See the MSDN docs on the OUTPUT clause for more details on what you can do with the OUTPUT clause - one of the most underused and most "unknown" features of SQL Server these days!
Another approach using OUTPUT clause and only one statement for inserting data in both destination tables:
--Parameters
DECLARE #TableGroup TABLE
(
Name NVARCHAR(100) NOT NULL
,Phone VARCHAR(10) NOT NULL
);
DECLARE #Type INT;
--End Of parameters
--Destination tables
DECLARE #FirstDestinationTable TABLE
(
FirstDestinationTableID INT IDENTITY(1,1) PRIMARY KEY
,Name NVARCHAR(100) NOT NULL
,Phone VARCHAR(10) NOT NULL
);
DECLARE #SecondDestinationTable TABLE
(
SecondDestinationTable INT IDENTITY(2,2) PRIMARY KEY
,FirstDestinationTableID INT NOT NULL
,[Type] INT NOT NULL
,CHECK([Type] > 0)
);
--End of destination tables
--Test1
--initialization
INSERT #TableGroup
VALUES ('Bogdan SAHLEAN', '0721200300')
,('Ion Ionescu', '0211002003')
,('Vasile Vasilescu', '0745600800');
SET #Type = 9;
--execution
INSERT #SecondDestinationTable (FirstDestinationTableID, [Type])
SELECT FirstINS.FirstDestinationTableID, #Type
FROM
(
INSERT #FirstDestinationTable (Name, Phone)
OUTPUT inserted.FirstDestinationTableID
SELECT tg.Name, tg.Phone
FROM #TableGroup tg
) FirstINS
--check records
SELECT *
FROM #FirstDestinationTable;
SELECT *
FROM #SecondDestinationTable;
--End of test1
--Test2
--initialization
DELETE #TableGroup;
DELETE #FirstDestinationTable;
DELETE #SecondDestinationTable;
INSERT #TableGroup
VALUES ('Ion Ionescu', '0210000000')
,('Vasile Vasilescu', '0745000000');
SET #Type = 0; --Wrong value
--execution
INSERT #SecondDestinationTable (FirstDestinationTableID, [Type])
SELECT FirstINS.FirstDestinationTableID, #Type
FROM
(
INSERT #FirstDestinationTable (Name, Phone)
OUTPUT inserted.FirstDestinationTableID
SELECT tg.Name, tg.Phone
FROM #TableGroup tg
) FirstINS
--check records
DECLARE #rc1 INT, #rc2 INT;
SELECT *
FROM #FirstDestinationTable;
SET #rc1 = ##ROWCOUNT;
SELECT *
FROM #SecondDestinationTable;
SET #rc2 = ##ROWCOUNT;
RAISERROR('[Test2 results] #FirstDestinationTable: %d rows; ##SecondDestinationTable: %d rows;',1,1,#rc1,#rc2);
--End of test1
Since you need all inserted identity values, look at the output clause of the insert statement: http://msdn.microsoft.com/en-us/library/ms177564.aspx