Remote query with variable using MSDASQL - tsql

I am trying to create a query for an SSRS report. I need to get the last 3 months transactions from a linked server (to an iSeries).
So I have built a SQL variable that I want to execute with OpenQuery
declare #EarliestDate varchar(8), #SQL VARCHAR(200), #sDate varchar(8)
SET #EarliestDate=CAST(DATEPART(YEAR,DATEADD(m,-3, getdate())) AS VARCHAR(4))
+ RIGHT('00' + CAST(DATEPART(mm, DATEADD(m,-3, getdate())) AS varchar(2)), 2)+ '01'
SELECT #SQL= 'SELECT * FROM YEDB03P WHERE TCDAT >' + '''' + #EarliestDate +'''' + ' ORDER BY TCDAT DESC'
print #EarliestDate
print #SQL
select * from openquery(BOCTEST2,#SQL)
But it seems that openquery doesn't like using a variable
What's the correct way to do this?

OPENQUERY does not accept variables for its arguments.
But you can move whole OPENQUERY statement into your dynamic SQL:
declare #EarliestDate varchar(8), #SQL VARCHAR(MAX), #sDate varchar(8)
SET #EarliestDate=CAST(DATEPART(YEAR,DATEADD(m,-3, getdate())) AS VARCHAR(4))
+ RIGHT('00' + CAST(DATEPART(mm, DATEADD(m,-3, getdate())) AS varchar(2)), 2)+ '01'
SELECT #SQL= 'select * from openquery(BOCTEST2, ''SELECT * FROM YEDB03P WHERE TCDAT >' + '''''' + #EarliestDate +'''''' + ' ORDER BY TCDAT DESC'')'
print #EarliestDate
print #SQL
EXEC #SQL

with help from Oleksandr Kucher I managed to do what I want with the below code (I added char(39) to the query string to force the quotes):
declare #EarliestDate varchar(8), #SQL NVARCHAR(1000), #sDate varchar(8)
SET #EarliestDate= CAST(DATEPART(YEAR,DATEADD(m,-3, getdate())) AS VARCHAR(4))
+ RIGHT('00' + CAST(DATEPART(mm, DATEADD(m,-2, getdate())) AS varchar(2)), 2)+ '01'
SELECT #SQL= 'insert into DBO.YEDB03P select * from openquery(BOCTEST2, ''SELECT * FROM YEDB03P WHERE TCDAT >'+char(39)+CHAR(39) + #EarliestDate +char(39)+CHAR(39) + ' ORDER BY TCDAT DESC'')'
--print #SQL
/*
The prints as
insert into DBO.YEDB03P select * from openquery(BOCTEST2, 'SELECT * FROM YEDB03P WHERE TCDAT >''20141001'' ORDER BY TCDAT DESC')
*/
exec sp_executesql #SQL
select * from PION..YEDB03P
thanks

Related

How do i can resolve this promblem?

I have an table include 1 column ID and 12 columns month (Month01 to Month12). If i have an parameter #month=9, how can i compare to get column Month01 to Month09 without Month10, Month11, Month12. Please help me!
Simo's answer is more elegant, but below is an alternative "basic" way to do this:
DECLARE #month INT
SET #month = 9
IF #Month = 1
BEGIN
SELECT Id, Month01
FROM MonthlyData
END
IF #Month = 2
BEGIN
SELECT Id, Month01, Month02
FROM MonthlyData
END
-- Repeat for months 3-9
IF #Month = 9
BEGIN
SELECT Id, Month01, Month02, Month03, Month04,
Month05, Month06, Month07, Month08, Month09
FROM MonthlyData
END
-- Repeat for months 10-12
See my SQL Fiddle.
declare #str varchar(1000)
SELECT #str= coalesce(#str + ', ', '') + a.name
FROM (
Select name from sys.columns
where object_id = OBJECT_ID('table_months')
and isnumeric(right(name,2))= 1 and name like 'month%'
and cast(right(name,2) as int) < '03') a
-- Instead of '03' you use a variable and assign required moths number
declare #sql nvarchar(100)
set #sql = 'select ID, '+ #str+' from table_months'
exec sp_executesql #sql
you may try this out also :)
DECLARE #month int = 9
DECLARE #Sql nvarchar(100) =''
DECLARE #pos int = 1
WHILE(#pos <= #month)
BEGIN
SET #Sql = #Sql + (',month' + right('00'+ rtrim(#pos), 2))
SET #pos = #pos + 1
END
SET #Sql= 'SELECT ID ' +#Sql + ' FROM table'
EXEC sp_executesql #Sql
DECLARE #month int
DECLARE #tableName nvarchar(128)
SET #month = 9;
SET #tableName = 'months' -- YOUR TABLE's NAME
DECLARE #query nvarchar(2048)
SET #query =
'SELECT id, ' + STUFF((SELECT DISTINCT ', ' + name
FROM sys.columns WHERE name LIKE'Month%'
AND object_id = OBJECT_ID(#tableName)
AND CONVERT(INT, RIGHT(name, 2)) <= #month
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
+ ' FROM ' + #tableName;
EXEC(#query)

How to create view for all tables in database?

I want to make views from all tables already exist in database that’s hard task to catch the tables one by one and make create view XXXX as select * from Table_name .I find something that it is possible with cursor and the code is :
DECLARE #TableName sysname
DECLARE #ColumnCount INT
DECLARE #ColumnID INT
DECLARE #SelectColumn NVARCHAR(500)
DECLARE #sql NVARCHAR(max) = ''
DECLARE QUERYINFO CURSOR FOR
SELECT
t.name AS TableName,
ccount.ColumnCount,
c.column_id AS ColumnID,
CASE WHEN c.column_id <> ccount.ColumnCount
THEN c.name + ', '
ELSE c.name
END AS SelectColumn
FROM sys.tables t
INNER JOIN sys.columns c ON t.object_id=c.object_id
INNER JOIN (
SELECT object_id,COUNT(*) AS ColumnCount
FROM sys.columns
GROUP BY object_id
) ccount ON t.object_id = ccount.object_id
ORDER BY t.Name,c.column_id
OPEN QUERYINFO
FETCH NEXT FROM QUERYINFO INTO #TableName,#ColumnCount,#ColumnID,#SelectColumn
WHILE ##FETCH_STATUS = 0
BEGIN
IF #ColumnID = 1
BEGIN
SET #sql = 'CREATE VIEW v_' + #TableName + ' AS SELECT ' + #SelectColumn
END
ELSE
BEGIN
SET #sql = #sql + #SelectColumn
END
IF #ColumnID = #ColumnCount
BEGIN
SET #sql = #sql + ' FROM ' + #TableName
EXEC sys.sp_executesql #sql
SET #sql = ''
END
FETCH NEXT FROM QUERYINFO INTO #TableName,#ColumnCount,#ColumnID,#SelectColumn
END
CLOSE QUERYINFO
DEALLOCATE QUERYINFO
but it has error and I don't know how solve it
This is what I would do with dynamic SQL; checking first to see if the view exists, then creating it with all of the columns (not by using SELECT * FROM...).
DECLARE #SQL nvarchar(MAX)
SET #SQL = N''
SELECT
#SQL = #SQL +
N'IF EXISTS(SELECT 1 FROM sys.objects WHERE name = N''v_' + t.name + N''' AND type = N''V'') BEGIN DROP VIEW [v_' + t.name + '] END CREATE VIEW [v_' + t.name + N'] AS SELECT ' +
STUFF(
(SELECT N',' + c.name
FROM
sys.columns AS c
WHERE
c.OBJECT_ID = t.OBJECT_ID
ORDER BY
column_id
FOR XML PATH(''), TYPE).value('.',N'nvarchar(max)')
,1,1,N'')
+ N' FROM [' + t.name + N'];'
FROM
sys.tables AS t
EXEC sp_executesql #SQL

Altering Multiple Tables at once

I'm trying to alter multiple SQL Server 2008 R2 tables at one time.
This is my code:
use DatabaseName
go
Declare #SchemaUsed varchar(20) = 'dbo'
create table #Tables
(
TableName varchar(100), Processed int
)
insert into #Tables
select top 1 table_name, 0
from INFORMATION_SCHEMA.TABLES
where TABLE_SCHEMA = #SchemaUsed
and table_type = 'Base Table'
and (TABLE_NAME like 'PM%' )
ORDER BY TABLE_NAME
DECLARE #TableName varchar(max)
DECLARE #SQL varchar(max)
WHILE EXISTS (select top 1 'x' from #Tables where Processed = 0)
BEGIN
SET #TableName = (select top 1 TableName from #Tables where Processed = 0)
Set #SQL = 'ALTER TABLE ' + #SchemaUsed + '.' + #TableName + ' ADD [identityID] bigint IDENTITY(1, 1) NOT NULL '
-- Set #SQL = '''' + #SQL + ''''
Print #SQL
EXEC #SQL;
update #Tables
set Processed = 1
where TableName = #TableName
END
drop table #Tables
I can't get this to work to save my life and get the following error:
Lookup Error - SQL Server Database Error: The name 'ALTER TABLE
dbo.PM1GTVLV ADD [identityID] bigint IDENTITY(1, 1) NOT NULL ' is not
a valid identifier.
I've also tried multiple string variations and using sp_executesql as well.
Can someone point out where I've gone wrong?
Try
DECLARE #SQL NVARCHAR(MAX);
EXEC sp_executesql #SQL;
Instead of EXEC #sql.
As an aside, this is a much more usable version of the same code IMHO:
DECLARE #SchemaUsed VARCHAR(20) = 'dbo';
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += CHAR(13) + CHAR(10) + N'ALTER TABLE '
+ QUOTENAME(#SchemaUsed) + '.'
+ QUOTENAME(name) + ' ADD [identityID]
BIGINT IDENTITY(1,1) NOT NULL;'
FROM sys.tables
WHERE SCHEMA_NAME([schema_id]) = #SchemaUsed
AND name LIKE 'PM%';
PRINT #sql;
--EXEC sp_executesql #sql;
Or even better:
DECLARE #SchemaUsed VARCHAR(20) = 'dbo';
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += CHAR(13) + CHAR(10) + N'ALTER TABLE '
+ QUOTENAME(#SchemaUsed) + '.'
+ QUOTENAME(name) + ' ADD [identityID]
BIGINT IDENTITY(1,1) NOT NULL;'
FROM sys.tables AS t
WHERE SCHEMA_NAME([schema_id]) = #SchemaUsed
AND name LIKE 'PM%'
AND NOT EXISTS (SELECT 1 FROM sys.columns AS c
WHERE [object_id] = t.[object_id]
AND c.is_identity = 1);
PRINT #sql;
--EXEC sp_executesql #sql;
To execute a character string, EXEC requires parenthesis around the string (or character variable) as shown in the BOL syntax:
EXEC (#SQL);

Stored Procedure Create Prob

Ok I don't know much about stored procedures, but does anyone know how I could write this as an SP. I think it's kinda getting there but not quite. basically what would I need to paste into my query to create it!:)
CREATE PROCEDURE sp_executesql
as
DECLARE
#cols AS NVARCHAR(MAX),
#y AS INT,
#sql AS NVARCHAR(MAX);
-- Construct the column list for the IN clause
SET #cols = STUFF(
(SELECT N',' + QUOTENAME(w) AS [text()]
FROM (SELECT DISTINCT WeekNo AS W FROM dbo.Items) AS W
ORDER BY W
FOR XML PATH('')),
1, 1, N'');
-- Construct the full T-SQL statement
-- and execute dynamically
SET #sql = N'SELECT *
FROM (SELECT ItemNo, WeekNo, Value
FROM dbo.Items) AS I
PIVOT(SUM(Value) FOR WeekNo IN(' + #cols + N')) AS P;';
EXEC sp_executesql #sql;
GO
Assuming the query statement is correct and you need just a SP structure it will be like this:
CREATE PROCEDURE SP_NAME
#variable1 type [input/output]
as
begin
--query
end
//to execute SP
EXEC SP_NAME 'valueForVariable1'
hope this helps
Got it. Just don't name provedure sp_executesql, name it get_items or something else.
new procedure:
CREATE PROCEDURE get_items
as
declare #cols AS NVARCHAR(MAX),
#y AS INT,
#sql AS NVARCHAR(MAX)
SET #cols = STUFF((SELECT N',' + QUOTENAME(w) AS [text()]
FROM (SELECT DISTINCT week_no AS W FROM weekly_items) AS W
ORDER BY W
FOR XML PATH('')),1, 1, N'');
SET #sql = N'SELECT *
FROM (SELECT item_no, week_no, totval
FROM weekly_items) AS I
PIVOT(SUM(totval) FOR week_no IN(' + #cols + N')) AS P;';
EXEC sp_executesql #sql
GO

Adding GUID parameter to a sql string

I am having complications adding a guid type to a sql string and getting the query to go. I have to write the sql this because I need to pass the name database as a parameter.
The following code is what I'm trying to do but it doesnt work. No matter what I do it doesn't read the GUID correctly. It gives me the following error when executing the stored proc. Probably because guid has "-" in them
Incorrect syntax near '-'.
Here's the code:
ALTER PROCEDURE [dbo].[templatesAndBaskets_Select]
#guid uniqueidentifier,
#DatabaseName varchar(50)
AS
BEGIN
Declare #sql varchar(max)
Set #sql=
'select soldtoid
from ' + #DatabaseName + '.templatesAndBaskets' +
' where ordergroupid = ' + CONVERT(varchar(max),#guid)
print #sql
EXECUTE SP_EXECUTESQL #sql
END
You probably just simply need to put single quotes around the GUID :
SET #sql =
N'SELECT soldtoid FROM ' + #DatabaseName + N'.templatesAndBaskets' +
N' WHERE ordergroupid = ''' + CONVERT(nvarchar(max), #guid) + N''''
That should result in a SQL statement something like this:
SELECT soldtoid FROM database.templatesAndBaskets
WHERE ordergroupid = '5E736CE7-5527-40ED-8499-2CA93FC7BC9C'
which is valid - yours without the single quotes around the GUID isn't valid...
Update: you also need to change your #sql variable to NVARCHAR for sp_Executesql - try this:
ALTER PROCEDURE [dbo].[templatesAndBaskets_Select]
#guid uniqueidentifier,
#DatabaseName NVARCHAR(50)
AS
BEGIN
DECLARE #sql NVARCHAR(MAX)
SET #sql =
N'SELECT soldtoid FROM ' + #DatabaseName + N'.templatesAndBaskets' +
N' WHERE ordergroupid = ''' + CONVERT(nvarchar(max), #guid) + N''''
PRINT #sql
EXECUTE sp_ExecuteSQL #sql
END
Does that work??
Put the #guid between '
ALTER PROCEDURE [dbo].[templatesAndBaskets_Select]
#guid uniqueidentifier,
#DatabaseName varchar(50)
AS
BEGIN
Declare #sql varchar(max)
Set #sql=
"select soldtoid from " + #DatabaseName + ".templatesAndBaskets" +
" where ordergroupid = '" + CONVERT(varchar(max),#guid)+"'"
print #sql
EXECUTE SP_EXECUTESQL #sql
END