Create a dynamic query - sql

I have made a stored procedure like this..
CREATE PROCEDURE [dbo].[sp_dataPull] #serverName nvarchar(30), #dbName nvarchar (30), #serverName2 nvarchar(30), #dbName2 nvarchar (30)
INSERT INTO sampleDatabase.dbo.WorkFlowCopy
([ServerName]
,[DBName]
,[ID]
,[ActivityDefinitionID]
,[ParentID]
,[Caption]
,[Description]
,[ShortDescription]
(SELECT #serverName, #dbName, sdb1.* from OPENDATASOURCE('SQLOLEDB',
'Data Source=phmnldb16\eaudit;user id=XXXX;password=XXXX').AUDIT_FSA_170_001.AUD170.Workflow sdb1)
UNION ALL
(SELECT #serverName2, #dbName2, sdb2.* from OPENDATASOURCE('SQLOLEDB',
'Data Source=phmnldb16\eaudit;user id=XXXX;password=XXXX').AUDIT_FSA_170_002.AUD170.Workflow sdb2)
This query's function is to move the the data from another server into specific table. Now, notice that I have 2 SELECT statements below and I have 4 parameters. It's because I combined 2 tables and moved it into another table.
The problem with this query is the fact that it is static. What If I need to combine 3 or more tables? Then I have to create another (SELECT and UNION ALL statement below and add another 2 or more parameters).. I want to make it DYNAMIC.

Try as follows:
CREATE PROCEDURE SP_DATAPULL #SERVER NVARCHAR(30),#DB NVARCHAR(30)
AS
BEGIN
DECLARE #SERVER NVARCHAR(MAX)='SERVER1,SERVER2,SERVER3,SERVER4,SERVER5'
DECLARE #DB NVARCHAR(MAX)='DB1,DB2,DB3,DB4,DB5'
DECLARE #SRV NVARCHAR(MAX),#DBN NVARCHAR(MAX),#QUERY NVARCHAR(MAX)
DECLARE #TEMP TABLE(SERVERNAME VARCHAR(100),DB VARCHAR(100))
WHILE(SELECT CHARINDEX(',',#SERVER))>0
BEGIN
SET #SRV=(SELECT SUBSTRING(#SERVER,0,CHARINDEX(',',#SERVER)))
SET #SERVER=SUBSTRING(#SERVER,LEN(#SRV)+2,LEN(#SERVER))
SET #DBN=(SELECT SUBSTRING(#DB,0,CHARINDEX(',',#DB)))
SET #DB=SUBSTRING(#DB,LEN(#DBN)+2,LEN(#DB))
INSERT INTO #TEMP VALUES (#SRV,#DBN )
END
INSERT INTO #TEMP VALUES (#SERVER,#DB )
SET #QUERY=' INSERT INTO sampleDatabase.dbo.WorkFlowCopy
([ServerName]
,[DBName]
,[ID]
,[ActivityDefinitionID]
,[ParentID]
,[Caption]
,[Description]
,[ShortDescription] '
DECLARE C CURSOR FOR
SELECT SERVERNAME,DB FROM #TEMP
OPEN C
FETCH NEXT FROM C INTO #SERVER,#DB
WHILE ##FETCH_STATUS=0
BEGIN
SET #QUERY=#QUERY+'(SELECT '''+#SERVER+''', '''+#DB+''', sdb1.* from OPENDATASOURCE(''SQLOLEDB'',
''Data Source=phmnldb16\eaudit;user id=XXXX;password=XXXX'').AUDIT_FSA_170_001.AUD170.Workflow sdb1) '
FETCH NEXT FROM C INTO #SERVER,#DB
END
CLOSE C
DEALLOCATE C
SET #QUERY=SUBSTRING(#QUERY,0,LEN(#QUERY)-LEN('UNION ALL'))
PRINT #QUERY
EXEC(#QUERY)
END

Related

SQL Server: Storing Query Result into Variable

I am trying to Concatenate Query Result for each Person into a Variable.
Cursor Extract Columname from #temp table and extract data from PersonTable
For Example:For PID=1(FName: John LName:Hill HomeCountry=US HomeState=CH)
123JohnHillUSCH
Person Table:
pid FName LName HomeCity HomeState
1 Pascal E New York NY
2 Steve F New York NY
CREATE table #Temp
([Id] int, [ColumnName] varchar(13))
;
INSERT INTO #Temp
([Id],[ColumnName])
VALUES
(1, 'EID'),
(2, 'FName'),
(3, 'LName'),
(4, 'HomeCountry'),
(5, 'HomeState')
;
SELECT * FROM #Temp
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
ALTER PROCEDURE [dbo].[up_Conv_GenerateResultsFromMappingTable]
#Param1 VARCHAR(30)
AS
SET NOCOUNT ON
DECLARE #ColName VARCHAR(100);
DECLARE #Result VARCHAR(MAX)
DECLARE #Cur as CURSOR;
SET #Cur = CURSOR FOR
SELECT columnName FROM #Temp
OPEN #Cur;
FETCH NEXT FROM #Cur INTO #ColName;
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #query nvarchar(MAX)
PRINT #Param1;
SET #Query='SELECT '+#ColName+' FROM dbo.PERSON where PID='+#Param1+''
PRINT #Query
EXECUTE sp_executesql #Query
, N'#Param1 varchar(30)',
#Param1
FETCH NEXT FROM #Cur INTO #ColName;
END
CLOSE #Cur;
DEALLOCATE #Cur;
Expected result
1,1PascalENewYorkNY
2,2SteveFNewYorkNY
In SQL Server 2012+, Why not just do
SELECT EID, CONCAT(EID, FName, LName, HomeCountry, HomeState) AS ConcatString, CreateDate
FROM Person
In SQL Server 2008R2 and below, it would have to be
SELECT EID, CAST(EID AS VARCHAR(20) + FName + LName + HomeCountry + HomeState AS ConcatString, CreateDate
FROM Person
And if You're wanting to return the results per user, you could parameterize it, and send in the EID individually from the source, or you could use a cursor...if you have absolutely no other option. If you're wanting to return the entire dataset, You can just consume the data straight from that dataset.

Values not passed to dynamic query in sql server

Is it possible to print the Dynamic select statement after passing the parameters values.When i print the SELECT #SQL.It is giving only select statement without parameter values.In my below procedure the dynamic select statement not giving correct output after passing the parameters.But when i directly passing the the parameter values into the select statement it is giving correct output.In my below procedure splitting function is working fine.Else part in
if statement is not working properly.
CREATE TYPE TableVariable AS TABLE
(
id int identity(1,1),
field_ids INT,
value VARCHAR(MAX)
)
Alter PROCEDURE Testing
(
#TableVar TableVariable READONLY,
#Catalog_id INT
)
AS
Declare #maxPK INT
Declare #pk INT
Declare #fid INT
Declare #is_List SMALLINT
Declare #val VARCHAR(MAX)
Declare #field_Type VARCHAR(50)
Declare #Where VARCHAR(MAX)
Declare #SQL NVARCHAR(MAX);
Set #pk = 1
BEGIN
BEGIN TRY
SET NOCOUNT ON;
Select #maxPK = count(*) From #TableVar
SELECT #Catalog_id
Set #SQL = 'SELECT DISTINCT v1.entity_id from values v1 inner join listings l ON v1.entity_id = l.entity_id WHERE l.c_id=#Catalog_id'
While #pk <= #maxPK
BEGIN
SELECT #fid= field_ids FROM #TableVar where id=#pk;
SELECT #val= value FROM #TableVar where id=#pk;
SELECT #field_Type=type,#is_List=is_list FROM FIELD WHERE ID=#fid
IF (#is_List = 0)
BEGIN
SET #SQL += ' and exists (select 1 from values v'+convert(varchar(15),#pk+1)+' where v1.entity_id = v'+convert(varchar(15),#pk+1)+'.entity_id and v'+convert(varchar(15),#pk+1)+'.field_id=#fid and(value IN(SELECT val FROM spliting(#val,'',''))))'
SELECT #fid
END
else IF (#is_List = 1 OR #field_Type = 'xy')
BEGIN
SET #SQL += ' and exists (select 1 from values v'+convert(varchar(15),#pk+1)+' where v1.entity_id = v'+convert(varchar(15),#pk+1)+'.entity_id and v'+convert(varchar(15),#pk+1)+'.field_id=#fid and(value in(#val)))'
SELECT #fid
END
Select #pk = #pk + 1
END
EXECUTE SP_EXECUTESQL #SQL, N'#Catalog_id int,#fid int,#val varchar(max)',#Catalog_id=#Catalog_id,#fid=#fid,#val=#val
SELECT #SQL
END TRY
BEGIN CATCH
END CATCH
END
DECLARE #DepartmentTVP AS TableVariable;
insert into #DepartmentTVP values(1780,'Smooth As Silk Deep Moisture Shampoo,Smooth As Silk Deeper Moisture Conditioner')
--insert into #DepartmentTVP values(1780,'Smooth As Silk Deeper Moisture Conditioner')
insert into #DepartmentTVP values(1782,'037-05-1129')
insert into #DepartmentTVP values(2320,'["fairtrade","usda_organic","non_gmo_verified"]')
SELECT * FROM #DepartmentTVP
EXEC Testing #DepartmentTVP,583
Yes right before the statment:
EXECUTE SP_EXECUTESQL #SQL, N'#Catalog_id int,#fid int,#val varchar(max)',#Catalog_id=#Catalog_id,#fid=#fid,#val=#val
type:
print #SQL

How to insert result of Stored Procedure into Temp Table without declaring Temp Table Columns

I want to insert the values of stored procedure into a temp table without predefining the columns for the temp table.
Insert Into #Temp1 Exec dbo.sp_GetAllData #Name = 'Jason'.
How can I do this ? I saw an option as below but can I do it without mentioning the server name ?
SELECT * INTO #TestTableT FROM OPENROWSET('SQLNCLI', 'Server=localhost;Trusted_Connection=yes;',
'EXEC tempdb.dbo.GetDBNames')
-- Select Table
SELECT *
FROM #TestTableT;
I could not find a possible solution without defining temp table schema and writing server name. So, I changed the code and the queries to handle with only known schema. Code example is as below
CREATE TABLE #TestTable ([name] NVARCHAR(256), [database_ID] INT);
INSERT INTO #TestTable
EXEC GetDBNames
SELECT * FROM #TestTable;
As provided in the link https://blog.sqlauthority.com/2013/05/27/sql-server-how-to-insert-data-from-stored-procedure-to-table-2-different-methods/
No-one said it had to be pretty:
CREATE PROCEDURE p AS
SELECT 1 as x, 2 as y, 3 as z
GO
DECLARE c CURSOR FOR
SELECT
name, system_type_name
FROM sys.dm_exec_describe_first_result_set_for_object(OBJECT_ID('p'), 0);
DECLARE #name sysname, #type sysname;
CREATE TABLE #t(fake int)
OPEN c
FETCH NEXT from c into #name, #type
WHILE (##FETCH_STATUS = 0)
BEGIN
EXEC ('ALTER TABLE #t ADD ' + #name + ' ' + #type)
FETCH NEXT from c into #name, #type
END
CLOSE C
DEALLOCATE c
ALTER TABLE #t DROP COLUMN fake;
INSERT INTO #t EXEC p;
GO

Declare a Cursor From a Table as Variable (In the Select-Statement)

I want to create a SP that have 2 String parameters for 2 table names. In the SP I use dynamic SQL to modify one of the tables, but the other is inside a cursor, and I cant use dynamic SQL after the "FOR"
ALTER PROCEDURE NameProcedure #SourceTable VARCHAR(100),#DestinationTable VARCHAR(100)
AS
BEGIN
DECLARE #AddressSource VARCHAR(100), #AddressDestination VARCHAR(100)
SELECT #AddressSource = '[Test_Toa].[dbo].[' + #SourceTable + ']'
SELECT #AddressDestination = '[Test_Toa].[dbo].[' + #DestinationTable + ']'
--Source Table columns
DECLARE #id int, #idmercado int, #idcadena int, #barcode nvarchar(255),#Complete_P nvarchar(MAX)
DECLARE #Cursor CURSOR
SET #Cursor = CURSOR FOR
--HEREE ITS MY PROBLEM :(!!!!!
SELECT id, idmercado, idcadena, barcode, precios + ',' FROM #AddressSource
OPEN #Cursor
FETCH NEXT
FROM #Cursor INTO #id,#idmercado,#idcadena,#barcode,#Complete_P
WHILE ##FETCH_STATUS = 0
BEGIN
--bla bla code
FETCH NEXT
FROM #Cursor INTO #id,#idmercado,#idcadena,#barcode,#Complete_P
END
CLOSE #Cursor
DEALLOCATE #Cursor
END
I just want to declare a cursor for the table that the user gives
Well, you need to write a dynamic sql statement. Just as an hint. You can copy the values from your given source table into a temp table, generate a cursor on the temp table, iterate through it and deallocate the cursor afterwards and drop the temp table. :-)
Here a short demo code:
DECLARE #sql nvarchar(max), #sourceTable nvarchar(255)
CREATE TABLE dbo.t1(id int, name nvarchar(200))
CREATE TABLE dbo.t2(id int, name nvarchar(200))
SET #sourceTable = N'dbo.t1'
CREATE TABLE #temp(id int, name nvarchar(200))
SET #sql = N'
INSERT INTO #temp(id,name)
SELECT id, name
FROM '+#sourceTable
EXEC(#sql)
DECLARE cur CURSOR FOR
SELECT id, name
FROM #temp
OPEN cur
DECLARE #id int, #name nvarchar(200)
FETCH NEXT FROM cur INTO #id, #name
WHILE ##fetch_status = 0 BEGIN
SELECT #id, #name -- demo output
FETCH NEXT FROM cur INTO #id, #name
END
-- cleanup
CLOSE cur
DEALLOCATE cur
DROP TABLE dbo.t1
DROP TABLE dbo.t2
DROP TABLE #temp
Beware, I just have written this in notepad without any database. But I'm quite sure it does it's job.
This just works if all available variants of #sourceTable have the same column specification. If not, you need to extract the needed columns from information schema and build a more dynamic code.

Pivoting SQL Server 2005 for unknown number of rows

My table is a dynamic one. E.g.:
id SUBJECT
1 his
2 math
3 sci
4 opt
5 ENG
6 SOC
The number of rows is not limited. There could be a hundred. I want output like this:
ID 1 2 3 4 5 6
HIS MATH SCI OPT ENG SOC
I could use a pivot query, but I would have to know the number of columns. How can I do this without knowing the number of columns in advance?
i got an answer but it's very tricky
create a table for all your records
count the records
create a table with that much number of columns
create a comma separated variable for the table which has records
then split the comma separated variables into multiple columns
here is the code
DECLARE #HEADDESC NVARCHAR(150)
DROP TABLE #HEADS
CREATE TABLE #HEADS
(
ID INT IDENTITY
,HEADS NVARCHAR(150)
,NU INT
)
DECLARE #NO INT;
SET #NO = 0
DECLARE C1 CURSOR FOR (
SELECT HEADDESC
FROM GMC.FEEHEAD_MASTER
WHERE CODE = 'GF' AND HEADDESC <> '')
OPEN C1
FETCH NEXT FROM C1 INTO #HEADDESC
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #HEADDESC
SET #NO = #NO+1
INSERT INTO #HEADS(HEADS,NU)
VALUES(#HEADDESC,#NO)
FETCH NEXT FROM C1 INTO #HEADDESC
END
--SELECT * FROM #HEADS
CLOSE C1
DEALLOCATE C1
DECLARE #COLNO INT
SET #COLNO = (SELECT COUNT(*) FROM #HEADS)
DECLARE #COLUMNS VARCHAR(8000)
SELECT #COLUMNS = COALESCE(#COLUMNS +','+ CAST(HEADS AS VARCHAR) ,
CAST(HEADS AS VARCHAR))
FROM #HEADS
--GROUP BY HEADS
DECLARE #value NVARCHAR(100)
SET #value = ',1,STUDENTIDNO,STUDENTNAME,'
SET #COLUMNS = #VALUE+#COLUMNS
SET #COLNO = #COLNO+4
--SELECT #COLUMNS
DROP TABLE #HEADSCOMMA
CREATE TABLE #HEADSCOMMA(HEADS NVARCHAR(3000))
INSERT INTO #HEADSCOMMA VALUES (#COLUMNS)
DROP TABLE #TEMP
CREATE TABLE #TEMP(COL1 NVARCHAR(1000))
DECLARE #SQL NVARCHAR(MAX)
DECLARE #COL NVARCHAR(1000)
DECLARE #COL1 INT
DECLARE #COLNAME NVARCHAR(1000)
SET #COL1 = 2
SET #COL = 'COL'
PRINT #COL1
--SET #COLNAME = #COL +CAST(#COL1 AS NVARCHAR(10))
WHILE #COL1 < =#COLNO
BEGIN
SET #COLNAME = #COL +CAST(#COL1 AS NVARCHAR(100))
PRINT #COLNAME
SET #SQL = 'ALTER TABLE #TEMP ADD '+#COLNAME+' NVARCHAR(100)'
EXEC(#SQL)
SET #COL1= #COL1+1
END
--SELECT * FROM #HEADSCOMMA -- COMMA SEPERATED VALUES
DECLARE #S VARCHAR(8000), #DATA VARCHAR(8000)
--DROP TABLE #NORMALISEDTABLE
--CREATE TABLE #NORMALISEDTABLE (HEADS NVARCHAR(200))
SELECT #S=''
WHILE EXISTS (SELECT * FROM #HEADSCOMMA WHERE HEADS>#S)
BEGIN
SELECT #S=HEADS FROM #HEADSCOMMA WHERE HEADS>#S
PRINT #S
SELECT #DATA=''''+REPLACE(#S,',',''',''')+''''
PRINT #DATA
INSERT INTO #TEMP
EXEC('SELECT '+#DATA)
END
SELECT * FROM #temp
will give the records
Dynamic SQL is an option.