Set variable value to array of strings - sql

I want to set a variable as a string of values. E.g.
declare #FirstName char(100)
select #FirstName = 'John','Sarah','George'
SELECT *
FROM Accounts
WHERE FirstName in (#FirstName)
I'm getting a syntax error in the line select #FirstName = 'John','Sarah','George':
Incorrect syntax near ','
Is there any way I can set the variable with many values?

declare #tab table(FirstName varchar(100))
insert into #tab values('John'),('Sarah'),('George')
SELECT *
FROM #tab
WHERE 'John' in (FirstName)

You're trying to assign three separate string literals to a single string variable. A valid string variable would be 'John, Sarah, George'. If you want embedded single quotes between the double quotes, you have to escape them.
Also, your actual SELECT won't work, because SQL databases won't parse the string variable out into individual literal values. You need to use dynamic SQL instead, and then execute that dynamic SQL statement. (Search this site for dynamic SQL, with the database engine you're using as the topic (as in [sqlserver] dynamic SQL), and you should get several examples.)

-- create test table "Accounts"
create table Accounts (
c_ID int primary key
,first_name varchar(100)
,last_name varchar(100)
,city varchar(100)
);
insert into Accounts values (101, 'Sebastian', 'Volk', 'Frankfurt' );
insert into Accounts values (102, 'Beate', 'Mueller', 'Hamburg' );
insert into Accounts values (103, 'John', 'Walker', 'Washington' );
insert into Accounts values (104, 'Britney', 'Sears', 'Holywood' );
insert into Accounts values (105, 'Sarah', 'Schmidt', 'Mainz' );
insert into Accounts values (106, 'George', 'Lewis', 'New Jersey' );
insert into Accounts values (107, 'Jian-xin', 'Wang', 'Peking' );
insert into Accounts values (108, 'Katrina', 'Khan', 'Bolywood' );
-- declare table variable
declare #tb_FirstName table(name varchar(100));
insert into #tb_FirstName values ('John'), ('Sarah'), ('George');
SELECT *
FROM Accounts
WHERE first_name in (select name from #tb_FirstName);
SELECT *
FROM Accounts
WHERE first_name not in (select name from #tb_FirstName);
go
drop table Accounts;
go

A quick way to turn your varchar variable to a table (array of values) is to have your FirstName variable as a whole varchar first and then use the STRING_SPLIT method.
declare #FirstName varchar(100)
select #FirstName = 'John,Sarah,George'
SELECT *
FROM Accounts
WHERE FirstName in (SELECT * FROM STRING_SPLIT(#FirstName, ','))

In SQL you can not have a variable array.
However, the best alternative solution is to use a temporary table.

I just want to extend #Code Save's answer
--collection table is required, since we cannot use directly arrays in TSQL
declare #CollectionTable table(FirstName varchar(100))
insert into #CollectionTable values('John'),('Sarah'),('George')
SELECT * FROM TargetTable
WHERE Name IN (SELECT * FROM #CollectionTable)
In this way we can use the result from the SELECT statement from our #CollectionTable to be evaluated in the IN operator. And of course we can re-use the #CollectionTable as many times as we need.

Related

How to compare String Variable with Integer

I have this table structure and and some sample data. I want return data for multiple ids via parameter. I have declared a parameter string and now I want to compare it with the column but it ain't allowing because ID is integer.
Can anybody give me any help here ?
CREATE TABLE EMPLOYEE
(
ID INT,
EMPLOYEE_NAME VARCHAR(50)
);
INSERT INTO EMPLOYEE VALUES (1, 'Isaac Frempong');
INSERT INTO EMPLOYEE VALUES (2, 'Eric Ortizz');
DECLARE #StrID VARCHAR(20) = '1, 2'
SELECT * FROM EMPLOYEE
WHERE ID = #StrID
SELECT * FROM EMPLOYEE
WHERE #StrID+',' LIKE '%'+cast(ID as varchar(20))+'%,'
Pretty bad performance as it will need to do a table scan but safe enough.
Generally though, your list of IDs should be a table variable you can do a proper JOIN or IN with
The easiest solution is to use dynamic SQL
DECLARE #sql VARCHAR(1000) = 'SELECT * FROM EMPLOYEE WHERE ID IN (' + #StrID + ')';
EXEC(#sql);
For SQL Server 2017+ you could use STRING_SPLIT a table-valued function that splits a string into rows of substrings
CREATE TABLE EMPLOYEE
(
ID INT,
EMPLOYEE_NAME VARCHAR(50)
);
INSERT INTO EMPLOYEE VALUES (1, 'Isaac Frempong');
INSERT INTO EMPLOYEE VALUES (2, 'Eric Ortizz');
DECLARE #StrID VARCHAR(20) = '1, 2'
SELECT * FROM EMPLOYEE
WHERE ID IN (SELECT value FROM STRING_SPLIT (#StrID,','))
Refer this working fiddle
Create a user defined table type and pass it as a parameter.
CREATE TYPE [UDT_INTIDS] AS TABLE(
[ID] [int] NOT NULL
)
GO
-- create a table value
DECLARE #IDs [UDT_INTIDS];
INSERT #IDs VALUES (1),(2);
-- search using table value.
SELECT e.*
FROM EMPLOYEE e
WHERE e.ID IN (SELECT p.ID FROM #IDs p);
-- or
SELECT e.*
FROM EMPLOYEE e
JOIN #IDs p ON e.ID = p.ID;
See https://learn.microsoft.com/en-us/sql/relational-databases/tables/use-table-valued-parameters-database-engine?view=sql-server-2017 for more details.
You can use the Cast in SQL-Server to cast it to the appropriate datatype. Source Here
WHERE CAST(ID AS VARCHAR(20)) = #StrID
Alternatively: You can use CONVERT function.
WHERE CONVERT(VARCHAR(20), ID) = #StrID

Return a constant set of key value pair

Imagine I have something like the following
SELECT 0 AS 'Key','No' AS 'Value'
UNION
SELECT 1 AS 'Key','YES' AS 'Value'
UNION
SELECT 2 AS 'Key','Maybe' AS 'Value'
....
....
How can I make above statement more readable so I can accommodate more constant key/value pair in above list in a single select statement? I don't want to create table variable or create a complex sql statement. Just a single select statement returning bunch of constant key/pair values.
You can use VALUES:
SELECT *
FROM (VALUES
(0, 'No'),
(1, 'Yes'),
(2, 'Maybe')
) t([Key], Value)
Table Value Constructor
Using a table value constructor.
VALUES ((0,'NO'),(1,'YES'),(2,'MAYBE'))
Understand you don't want to create a table variable
I use the accepted answer a lot +1
Just pointing out a table variable lets you declare type and primary key
declare #tbl table ([key] tinyint primary key, [value] varchar(12));
insert into #tbl values (1, 'one')
, (2, 'two')
, (3, 'three');
select * from #tbl order by [key];

Insert multiple rows using single insert statement

I am trying to insert into table variable using following query.
but its throwing an error.
Please help on inserting multiple selects using single insert statement.
DECLARE #AddressRecordsToPurge TABLE
(
RowID INT NOT NULL PRIMARY KEY IDENTITY(1,1),
GUIDValue Nvarchar(max) ,
GuidColumn Nvarchar(max) ,
GuidTable Nvarchar(max)
)
Insert Into #AddressRecordsToPurge values ( (Select
EMPLOYMENTSEQUENCENUMBER FROM ACCOUNTANTSREFERENCE WHERE
CustomerNumber = #CustomerNumber AND Customerversionnumber =
#CustomerVersionNumber AND EMPLOYMENTSEQUENCENUMBER IS NOT
NULL), 'EMPLOYMENTSEQUENC ENUMBER', 'ACCOUNTANTSREFERENCE');
My select statement returns multiple values and I want to have it this way only. Please help!
Your syntax is slightly off:
Insert Into #AddressRecordsToPurge (GuidValue, GuidColumn, GuidTable)
SELECT EMPLOYMENTSEQUENCENUMBER, 'EMPLOYMENTSEQUENCENUMBER', 'ACCOUNTANTSREFERENCE'
FROM ACCOUNTANTSREFERENCE
WHERE CustomerNumber = #CustomerNumber
AND Customerversionnumber = #CustomerVersionNumber
AND EMPLOYMENTSEQUENCENUMBER IS NOT NULL;

How to retrieve a value from sql server (While inserting a data use a Stuff function)

I am using stuff function to insert a value which is separated by comma.
Now I want to retrieve those value and each value which is separated by comma is unique and store these value in another variable and use them
e.g product_id(10,5,9).
This is one row data now I want to read and store there id in separate variable
Check this example. may be work for you. But this is for a single record, if you wish, then you need again a extra loop above this loop.
declare #S varchar(30)
set #S = '10,5,9'
declare #tempVariableTostoreID int
while len(#S) > 0
begin
--here you can store it on another variable
select #tempVariableTostoreID = LOWER( left(#S, charindex(',', #S+',')-1) )
select #tempVariableTostoreID
set #S = stuff(#S, 1, charindex(',', #S+','), '')
end
May I ask a question, why you split and need to store in again variable. What is your goal?
Updated
As per you comment check this. First you create a table-valued function from any of this link and then use this sqlscript.
Create Split function:
http://ole.michelsen.dk/blog/split-string-to-table-using-transact-sql.html
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=50648
Splitting delimited values in a SQL column into multiple rows
How to split a single column values to multiple column values?
https://dba.stackexchange.com/questions/21078/t-sql-table-valued-function-to-split-a-column-on-commas
create table product (productid int, productname ntext)
create table orderhistory (orderID int, username varchar(100), productid varchar(100) )
insert into product values(1, 'P1')
insert into product values(2, 'P2')
insert into product values(3, 'P3')
insert into product values(4, 'P4')
insert into product values(5, 'P5')
select orderid, username , p.productname from
(
select oh.orderid, oh.username ,item from orderhistory oh
cross apply dbo.Split(oh.productid , ',')
)
a join product p on p.productid = a.item

Insert a row if it doesn't exist via query

I am trying to write a query that will insert a group of people into a table if that person does not exist. For example, I have table full of people and I need to add more people into the database and I don't know if they are already there. I do know that the social security number (ssn) will never be the same for two people. Could a query be used to check if the ssn is in the table and if not insert the person into the table? If the ssn is in the table then go to the next person and check?
I was thinking about using a stored procedure, but I do not have any rights to create a store procedure.
You can insert your data into a table variable or temp table and then INSERT INTO table from temp table where it does not exists in your table.
DECLARE #Inserted AS TABLE
(
NAME VARCHAR(50)
,SSN DECIMAL(10, 0)
)
INSERT INTO #Inserted
( NAME, SSN )
VALUES ( 'Bob', 123456789 )
, ( 'John', 123546789 )
, ( 'James', 123456798 )
INSERT INTO MyTable
SELECT *
FROM #Inserted AS i
LEFT OUTER JOIN MyTable AS m
ON i.SSN = m.SSN
WHERE m.SSN IS NULL
Here are a couple ideas to get you started. I use MERGE a lot because it offers so much control. You could also look into the IN clause as part of a WHERE predicate in the INSERT SELECT statement.
MERGE
DECLARE #PERSONTABLE TABLE (ID INT PRIMARY KEY IDENTITY(1,1), FirstName VARCHAR(max))
INSERT INTO #PERSONTABLE (FirstName) VALUES ('Bill'),('Sally'),('Bob')
DECLARE #NEWPEOPLE TABLE (FirstName VARCHAR(max))
INSERT INTO #NEWPEOPLE (FirstName) VALUES ('Jim'), ('Sally')
--MERGE
MERGE INTO #PERSONTABLE AS T
USING #NEWPEOPLE AS S
ON (T.FirstName = S.FirstName)
WHEN NOT MATCHED BY TARGET THEN
INSERT (FirstName) VALUES (S.FirstName);
SELECT * FROM #PERSONTABLE
EXCEPT
DECLARE #PERSONTABLE TABLE (ID INT PRIMARY KEY IDENTITY(1,1), FirstName VARCHAR(max))
INSERT INTO #PERSONTABLE (FirstName) VALUES ('Bill'),('Sally'),('Bob')
DECLARE #NEWPEOPLE TABLE (FirstName VARCHAR(max))
INSERT INTO #NEWPEOPLE (FirstName) VALUES ('Jim'), ('Sally')
--EXCEPT
INSERT INTO #PERSONTABLE (FirstName)
SELECT FirstName FROM #NEWPEOPLE
EXCEPT
SELECT FirstName FROM #PERSONTABLE
SELECT * FROM #PERSONTABLE
You could do it like this if the new people are in another table. If not, then use Vladimir's solution.
INSERT INTO People(ssn, firstname, lastname)
SELECT ssn, firstname, lastname
FROM newpeople
WHERE ssn not in (select ssn from people )
INSERT INTO People(ssn, firstname, lastname)
SELECT np.ssn, np.firstname, np.lastname
FROM newpeople np
LEFT JOIN People p on np.ssn = p.ssn
WHERE p.ssn IS NULL
Here's another option I use a lot. Normally joins are better than sub-selects... if the joined table value is null you know you don't have a hit in the joined table.