SQL function to lookup ID from Name - sql-server

Our reference tables each have a "Name" field with a unique index, plus an ID primary key. Is it possible to write a function like ID(#tableName varchar(100), #name varchar(100) that will return the ID? "EXEC" within functions does not seem to be allowed. If necessary we could specify that tables that this would work with inside the function.

Try using this approach (example for 2 simple tables)
CREATE TABLE Table1 (Id int, Name varchar(100));
INSERT INTO Table1 VALUES (1, 'Name1InTable1');
INSERT INTO Table1 VALUES (2, 'Name2InTable1');
INSERT INTO Table1 VALUES (3, 'Name3InTable1');
CREATE TABLE Table2 (Id int, Name varchar(100));
INSERT INTO Table1 VALUES (1, 'Name1InTable2');
INSERT INTO Table1 VALUES (2, 'Name2InTable2');
INSERT INTO Table1 VALUES (3, 'Name3InTable2');
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER FUNCTION dbo.f_GetIdFromTableByName
(
#tableName varchar(100), #name varchar(100)
)
RETURNS int
AS
BEGIN
DECLARE #Id int;
IF #tableName = 'Table1'
BEGIN
SELECT #Id = Id
FROM Table1
WHERE Name = #name;
END;
IF #tableName = 'Table2'
BEGIN
SELECT #Id = Id
FROM Table2
WHERE Name = #name;
END;
RETURN #Id
END
GO
Run function
SELECT dbo.f_GetIdFromTableByName('Table2','Name2InTable2')

Related

Create procedure that will insert or update data from one temporary table to other 4 tables

I need to
Create procedure that will
insert or update data from the source table into the target1 table
Insert data into target2 table AND will get inserted ID
from target1, target2 tables
Insert them into target table3
Insert target1.ID into target4 table
the source table is a temporary table, and I use bulk copy to insert big data into that table and then move data to target tables for performance.
MSPCompanies - insert or update по признаку INN
MSPDownloads insert
MSPAccepted insert MSPCompanies.ID и MSPDownloads.ID
MSPAcceptedNow insert MSPCompanies.ID
insert or update in MSPCompanies I have done with MERGE
BEGIN
BEGIN TRY
BEGIN TRANSACTION
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
MERGE INTO [MSPCompanies] AS [Target]
USING [MSPTempTable] AS [Source]
ON Target.INN = Source.INN
WHEN MATCHED THEN
UPDATE SET
Target.Name = Source.Name,
Target.ShortName = Source.ShortName,
Target.FIO = Source.FIO,
Target.SubjectType = Source.SubjectType,
Target.SubjectCategory = Source.SubjectCategory,
#MSPCompaniesId = Target.MSP_Companies_ID
WHEN NOT MATCHED THEN
INSERT
(INN, Name, ShortName, FIO, SubjectType, SubjectCategory)
VALUES
(Source.INN, Source.Name, Source.ShortName, Source.FIO, Source.SubjectType, Source.SubjectCategory);
IF #MSPCompaniesId IS NULL
BEGIN
SET #MSPCompaniesId = CAST(SCOPE_IDENTITY() as [int]);
END
SELECT #MSPCompaniesId
--BEGIN
INSERT INTO dbo.MSPAcceptedNow
(MSP_Company_ID)
VALUES(#MSPCompaniesId)
but after it seems that can't do other operations with oterh three tables, and trying to do it with insert - update, but anyway can't do that.
BEGIN TRANSACTION MoveDataFromMSPTempTableT;
UPDATE t
SET
Name = s.Name,
ShortName = s.ShortName,
FIO = s.FIO,
SubjectType = s.SubjectType,
SubjectCategory = s.SubjectCategory
FROM MSPCompanies t
JOIN MSPTempTable s
ON s.INN = t.INN;
INSERT INTO MSPCompanies
SELECT s.INN,
s.Name,
s.ShortName,
s.FIO,
s.SubjectType,
s.SubjectCategory
FROM MSPTempTable s
LEFT JOIN MSPCompanies t
ON s.INN = t.INN
WHERE t.INN IS NULL;
COMMIT TRANSACTION MoveDataFromMSPTempTableT;
Thank you.
You cannot use a variable to track all the changes, but you track all the changes with OUTPUT.
if object_id('dbo.[MSPCompanies]') is not null drop table dbo.[MSPCompanies];
if object_id('dbo.[MSPTempTable]') is not null drop table dbo.[MSPTempTable];
create table dbo.[MSPTempTable]
(
MSP_Companies_ID int identity(1,1),
INN varchar(5) primary key clustered,
[Name] varchar(20),
ShortName varchar(20),
FIO varchar(20),
SubjectType varchar(20),
SubjectCategory varchar(20)
);
insert into dbo.[MSPTempTable] (inn,
[Name]
,ShortName
,FIO
,SubjectType
,SubjectCategory) values ('a','a','a','a','a','a'), ('a2','a2','a2','a2','a2','a2');
create table dbo.[MSPCompanies]
(
MSP_Companies_ID int identity(1,1),
INN varchar(5) primary key clustered,
[Name] varchar(20),
ShortName varchar(20),
FIO varchar(20),
SubjectType varchar(20),
SubjectCategory varchar(20)
);
insert into dbo.[MSPCompanies] (inn,
[Name]
,ShortName
,FIO
,SubjectType
,SubjectCategory) values ('a','a','a','a','a','a');
begin tran
set xact_abort on;
SET NOCOUNT ON;
DECLARE #SummaryOfChanges TABLE(
CompanyID int,
Change VARCHAR(20)
);
MERGE INTO [MSPCompanies] AS [Target]
USING [MSPTempTable] AS [Source]
ON Target.MSP_Companies_ID = Source.MSP_Companies_ID
WHEN MATCHED THEN
UPDATE SET
Target.Name = Source.Name,
Target.ShortName = Source.ShortName,
Target.FIO = Source.FIO,
Target.SubjectType = Source.SubjectType,
Target.SubjectCategory = Source.SubjectCategory
WHEN NOT MATCHED THEN
INSERT (INN, Name, ShortName, FIO, SubjectType, SubjectCategory)
VALUES (Source.INN, Source.Name, Source.ShortName, Source.FIO, Source.SubjectType, Source.SubjectCategory)
OUTPUT inserted.MSP_Companies_ID, $action INTO #SummaryOfChanges;
SELECT * from dbo.[MSPCompanies]
SELECT * from #SummaryOfChanges;
if ##TRANCOUNT > 0
rollback tran;

jdbc sql error: statement did not return a result set

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".

##ROWCOUNT returning 1 when no UPDATE made

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

Insert a row to SQL table

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

Inserting batch of rows into two tables in SQL Server 2008

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

Resources