Create a global variable list/set in sql server - sql

DECLARE #Companies_List char(25)
SET #Companies_List = ('Amazon','Google','Facebook')
select *
from companies
where name in #Companies_List
I'm new to SQL Server. I'm trying to create a global set containing the values that I want to use in the SQL where clause, but apparently the above script wouldn't work. Any idea how I should do it? Many thanks!

I would create a TABLE variable and do a JOIN to it for a list like this:
DECLARE #Companies_List TABLE
(
Name Char(25)
)
INSERT #Companies_List (Name)
VALUES ('Amazon'), ('Google'), ('Facebook')
SELECT C.*
FROM Companies C
JOIN #Companies_List CL ON C.Name = CL.Name
If you want something more concrete, you should make a physical TABLE.

Related

How to assign SQL query result to variable?

I need assign the following SQL Server's query result value to the variable called #value1
SELECT *
FROM customer
WHERE apo_id = '2589';
How can I do this in SQL Server?
1 - First declare your variable of type table.
declare #value1 table(
--YOUR TABLE DEFINITION ex: ValueId int,
)
2 - Insert into your variable
insert into #value1 select * from customer WHERE apo_id = '2589';
Hope that helps, thanks.
It won't really be a variable but a table because you are selecting multiple fields (e.g. Select *) but, you can select INTO a temporary table like this:
SELECT *
INTO #myTempTable
FROM customer
WHERE apo_id = '2589';

How do I create a variable/parameter that is a string of values in SQL SSMS that I can use as a substitute in my where clause?

This may be a very basic question, but I have been struggling with this.
I have a SSMS query that I'll be using multiple times for a large set of client Ids. Its quite cumbersome to have to amend the parameters in all the where clauses every time I want to run it.
For simplicity, I want to convert a query like the one below:
SELECT
ID,
Description
From TestDb
Where ID in ('1-234908','1-345678','1-12345')
to a query of the format below so that I only need to change my variable field once and it can be applied across my query:
USE TestDb
DECLARE #ixns NVARCHAR(100)
SET #ixns = '''1-234908'',''1-345678'',''1-12345'''
SELECT
ID,
Description
From TestDb
Where ID IN #ixns
However, the above format doesn't work. Can anyone help me on how I can use a varchar/string variable in my "where" clause for my query so that I can query multiple IDs at the same time and only have to adjust/set my variable once?
Thanks in advance :D
The most appropriate solution would be to use a table variable:
DECLARE #ixns TABLE (id NVARCHAR(100));
INSERT INTO #ixns(id) VALUES
('1-234908'),
('1-345678'),
('1-12345');
SELECT ID, Description
FROM TestDb
WHERE ID IN (SELECT id FROM #ixns);
You can load ids to temp table use that in where condition
USE TestDb
DECLARE #tmpIDs TABLE
(
id VARCHAR(50)
)
insert into #tmpIDs values ('1-234908')
insert into #tmpIDs values ('1-345678')
insert into #tmpIDs values ('1-12345')
SELECT
ID,
Description
From TestDb
Where ID IN (select id from #tmpIDs)
The most appropriate way is to create a table type because it is possible to pass this type as parameters.
1) Creating the table type with the ID column.
create type MyListID as table
(
Id int not null
)
go
2) Creating the procedure that receives this type as a parameter.
create procedure MyProcedure
(
#MyListID as MyListID readonly
)
as
select
column1,
column2
...
from
MyTable
where
Id in (select Id from #MyListID)
3) In this example you can see how to fill this type through your application ..: https://stackoverflow.com/a/25871046/8286724

SQL - Dynamic Lookup with Regex

I would like to determine the ownership of a folder. Therefore every folder has a constant naming convention, which is stored in the table OWNER(ident_string).
Using the ident_string I want to determine the owner_id and write it (update) into table FOLDER(owner_id).
I have following tables in Postgresql:
create table owner(
owner_id serial PRIMARY KEY,
owner_name varchar(100),
ident_string varchar(100));
create table folder(
folder_id serial PRIMARY KEY,
folder_name varchar(80),
folder_path varchar(800),
owner_id integer references owner(owner_id));
insert into owner (owner_name, ident_string) values ('Jonny English','b-jonny');
insert into owner (owner_name, ident_string) values ('Hanna Babara','b-hanna');
insert into owner (owner_name, ident_string) values ('Mary Marmelade','b-mary');
insert into folder (folder_name,folder_path) values ('b-jonny-20130101','/archive/backup/b-jonny-20130101');
insert into folder (folder_name,folder_path) values ('b-jonny-20130103','/archive/backup/b-jonny-20130103');
insert into folder (folder_name,folder_path) values ('b-hanna-20140101','/archive/backup/b-jonny-20140101');
insert into folder (folder_name,folder_path) values ('b-mary-20120303','/archive/backup/b-mary-20120303');
I think the only possiblity to do so is via PL/pgSQL:
iterate for folder_name in FOLDER over every row in OWNER
check for every ident_string to lookup the owner_id.
Could somebody help me out?
Maybe something similar to the following?
update folder set folder.owner_id = owner.owner_id from folder join owner on folder_name like owner.ident_string + '%'
(like is the method for regexs in sql)
Try this:
update folder as f
set owner_id = o.owner_id
from owner as o
where o.ident_string = left(f.folder_name,length(o.ident_string));
-g
You could create table folder in one sentence:
insert into folder (folder_name,folder_path,owner_id)
with tmp (folder_name,folder_path) as
(
select 'b-jonny-20130101','/archive/backup/b-jonny-20130101' union all
select 'b-jonny-20130103','/archive/backup/b-jonny-20130103' union all
select 'b-hanna-20140101','/archive/backup/b-jonny-20140101' union all
select 'b-mary-20120303','/archive/backup/b-mary-20120303'
)
select folder_name,folder_path,o.owner_id
from tmp
join owner o
on tmp.folder_name ~ o.ident_string;
select * from owner;
Use a regular expression (~), it's more powerful.
See SQL FIDDLE DEMO

Select all values from all tables with specific table name

EDIT original question:
Our UDW is broken out into attribute and attribute list tables.
I would like to write a data dictionary query that dynamically pulls in all column values from all tables that are like %attr_list% without having to write a series of unions and update or add every time a new attribute list is created in our UDW.
All of our existing attribute list tables follow the same format (number of columns, most column names, etc). Below is the first two unions in our existing view which I want to avoid updating each time a new attribute list table is added to our UDW.
CREATE VIEW [dbo].[V_BI_DATA_DICTIONARY]
( ATTR_TABLE
,ATTR_LIST_ID
,ATTR_NAME
,ATTR_FORMAT
,SHORT_DESCR
,LONG_DESCR
,SOURCE_DATABASE
,SOURCE_TABLE
,SOURCE_COLUMN
,INSERT_DATETIME
,INSERT_OPRID
)
AS
SELECT 'PREAUTH_ATTR_LIST' ATTR_TABLE
,[PREAUTH_ATTR_LIST_ID] ATTR_LIST_ID
,[ATTR_NAME] ATTR_NAME
,[ATTR_FORMAT] ATTR_FORMAT
,[SHORT_DESCR] SHORT_DESCR
,[LONG_DESCR] LONG_DESCR
,[SOURCE_DATABASE] SOURCE_DATABASE
,[SOURCE_TABLE] SOURCE_TABLE
,[SOURCE_COLUMN] SOURCE_COLUMN
,[INSERT_DATETIME] INSERT_DATETIME
,[INSERT_OPRID] INSERT_OPRID
FROM [My_Server].[MY_DB].[dbo].[PREAUTH_ATTR_LIST]
UNION
SELECT 'SAVINGS_ACCOUNT_ATTR_LIST'
,[SAVINGS_ACCOUNT_ATTR_LIST_ID]
,[ATTR_NAME]
,[ATTR_FORMAT]
,[SHORT_DESCR]
,[LONG_DESCR]
,[SOURCE_DATABASE]
,[SOURCE_TABLE]
,[SOURCE_COLUMN]
,[INSERT_DATETIME]
,[INSERT_OPRID]
FROM [My_Server].[MY_DB].[dbo].[SAVINGS_ACCOUNT_ATTR_LIST]'
Something like this might work for you if all tables contain the same columns.
Just change the temp table and the selected columns to match your own columns.
CREATE TABLE #results (
ATTR_TABLE SYSNAME,
ATTR_LIST_ID INT,
ATTR_NAME NVARCHAR(50),
ATTR_FORMAT NVARCHAR(50),
SHORT_DESCR NVARCHAR(50),
LONG_DESCR NVARCHAR(255),
SOURCE_DATABASE NVARCHAR(50),
SOURCE_TABLE NVARCHAR(50),
SOURCE_COLUMN NVARCHAR(50),
INSERT_DATETIME DATETIME,
INSERT_OPRID INT
);
INSERT INTO #results
EXEC sp_MSforeachtable #command1 =
'
SELECT ''?''
, *
FROM ?
WHERE ''?'' LIKE ''%ATTR_LIST%''
'
SELECT *
FROM #results
DROP TABLE #results
EDIT: Updated my example with your columns. Because you use different column name for ATTR_LIST_ID in each table I changed the select to SELECT *. Obviously I don't know the data types of your columns so you have to change them.
This won't work in a view but you could create a stored procedure.
For SQL Server you should be able to use something like this:
SELECT c.name AS ColName, t.name AS TableName
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE t.name LIKE '%attr_list%'
And this will include views as well as tables
SELECT COLUMN_NAME, TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE '%attr_list%'
If using MS SQL Server check out the sys catalog views. You can use sys.tables and join to sys.columns to get your tables and columns. sys.extended_properties can get you description information, if entered.

Solutions for tracking how many times certain parameters are used in a stored procedure SQL Server 2008

In my database have tables with structures similar to:
create table ItemNameSearches
(ItemName varchar(50) not null,timesSearched int not null,
primary key(ItemName))
and
create table ItemList
(ItemName varchar(50),
primary key (ItemName))
My idea is to have people enter in through a webform a comma-separated list of values so that they can get information about certain items. The table ItemList contains information about the item for which they searched (although the table structure doesn't reflect that in this example). If, however, the item searched for doesn't appear in the ItemList table, I would like for that ItemName to be inserted into the ItemNameSearches so I could have a better idea of what people are searching for.
Scenario 1: an item is searched for the first time and a new row is inserted into the ItemNameSearches table. I'm pretty sure this is an area for triggers, but I'm not familiar with using them so I wrote the following stored procedure:
create proc spSearchItemName
#itemName1 varchar(50)
,#itemName2 varchar(50) = null
,#itemName3 varchar(50) = null
,#itemName4 varchar(50) = null
as
begin
;with searchList
as
(select x.itemName
from (values (#itemName1)
,(#itemName2)
,(#itemName3)
,(#itemName4)
) as x(itemName)
where x.itemName is not null
--these are optional parameters just to give the user more flexibility
--on if they want to look at multiple items at once or not
)
insert into ItemNameSearches(itemName,timesSearched)
values
(
(select sl.itemName
from searchList as sl
left outer join ItemList as il
on il.itemName=sl.itemName
where il.itemName is null
--this subquery finds the items searched for that are not present in the
--itemlist table and sets timesSearched =1 for each
),1
)
end
This is well and good for the items that are searched for that do not appear in the ItemList table, but I would have to do something like the following procedure if they DID search for an item that was in the ItemList table
;with searchList
as
(select x.itemName
from (values ('item 1')
,('item 2')
,('item 3')
,('item 5')
) as x(itemName)
)
update ins
set timesSearched = timesSearched +1
from ItemNameSearches as ins
where itemName in
(select itemName from searchList)
So this will add 1 to the number of times an item was searched for if it exists in the ItemList table. Can someone provide a neat manner of how to solve these two different situations? Is this something that is a good candidate for triggers?
Thanks to #Gordon Linoff for providing the direction of using the merge statement, it ended up working perfectly for what I wanted to do. I ended up using the following sproc and it works fine.
alter proc spSearchDrugName
#drugName1 varchar(50)
,#drugName2 varchar(50) = null
,#drugName3 varchar(50) = null
,#drugName4 varchar(50) = null
,#drugName5 varchar(50) = null
as
begin
declare #searchList table(drugName varchar(50))
insert into #searchList
values (#drugName1)
,(#drugName2)
,(#drugName3)
,(#drugName4)
,(#drugName5)
merge DrugListSearches as d
using(select drugName from #searchList where drugName is not null) as s
on s.drugName = d.drugName
when matched then
update set d.timesSearched = d.timesSearched + 1
when not matched then
insert (drugname,timesSearched) values (s.drugName,1);
end