Dynamic Query w/ Quotes issue - tsql

I'm trying to write a dynamic query that produces the same results as the following, but replaces the fixed tablename with a variable.
SELECT *
WHERE tableName = 'Table2A'
works fine but
DECLARE #tablename AS NVARCHAR(100)
SET #tablename = N'Table2A'
DECLARE #execquery AS NVARCHAR(MAX)
SET #execquery = N'
SELECT *
WHERE tableName = ''' + QUOTENAME(#tablename) + N''''
EXECUTE sp_executesql #execquery
returns no records. What am I doing wrong?

Aside from the fact that your SQL statement is invalid, QUOTENAME() simply places brackets "[]" around the supplied variable. Replace the EXECUTE statement with a PRINT statement, and you'll get the following results:
DECLARE #tablename AS NVARCHAR(100)
SET #tablename = N'Table2A'
DECLARE #execquery AS NVARCHAR(MAX)
SET #execquery = N'
SELECT *
WHERE tableName = ''' + QUOTENAME(#tablename) + N''''
PRINT #execquery
--EXECUTE sp_executesql #execquery
RESULTS:
SELECT *
WHERE tableName = '[Table2A]'

Related

The name "xxx" is not permitted in this context. Valid expressions are constants, constant expressions, and (in some contexts) variables

I want to separate a table's columns into two set (1st set = bottom 50%, 2nd set = top 50%, there is a reason why I am not using a median formula in this case and I know that there will be a case when the count([ORDINAL_POSITION]) will be an odd number, then I won't get accurate result.) to achieve this I am trying to use INFORMATION_SCHEMA.COLUMNS, but I can't figure it out why I got the following error message:
The name "sometable" is not permitted in this context. Valid expressions are constants, constant expressions, and (in some contexts) variables. Column names are not permitted.
DECLARE #table2 NVARCHAR(MAX)
DECLARE #table_op_mid INT
SET #table2 = 'sometable'
SELECT #table_op_mid = 'SELECT ROUND(MAX([ORDINAL_POSITION])/2,0) AS OP FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '+#table2+''
PRINT (table_op_mid)
EXEC (#table_op_mid)
1st problem is that #table_op_mid is declared as INT instead of VARCHAR
2nd problem is that #table2 need extra quotes when used in TABLE_NAME comparision
3rd problem is that table_op_mid is missing # symbol, should be PRINT(#table_op_mid)
DECLARE #table2 NVARCHAR(MAX)
DECLARE #table_op_mid NVARCHAR(MAX)
SET #table2 = 'sometable'
SELECT #table_op_mid = 'SELECT ROUND(MAX([ORDINAL_POSITION])/2,0) AS OP FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '''+#table2+''''
PRINT (#table_op_mid)
EXEC (#table_op_mid)
EDIT
After your comment.. It is the same problem as before.. #SQL_columnnull_part_2 should be VARCHAR instead of INT
declare #db2 varchar(max) = 'MyDb'
declare #table2 varchar(max) = 'sometable'
declare #SQL_columnnull_part_2 varchar(max) = ''
Also, your new query will not work because STRING_AGG doesn't add last separator, so you should move the comparision term in the 1st parameter and keep in separator only the ';'
SELECT #SQL_columnnull_part_2 = STRING_AGG(
'UPDATE ' + #db2 + '.[dbo].' + #table2 + ' WITH (TABLOCK) SET ' + QUOTENAME(COLUMN_NAME,'['']') + ' = NULL WHERE ' + QUOTENAME(COLUMN_NAME,'['']') + ' = ''''',
'; '
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #table2
AND [ORDINAL_POSITION] > #table_op_mid

result of sp_executesql in a variable

How can I get the output of the below query in a variable without temp table?
DECLARE #Q1 NVARCHAR(300)
DECLARE #Q2 NVARCHAR(300)
DECLARE #Q3 NVARCHAR(300)
SET #Q1 = 'SELECT ' +' ' + #formfieldpath
SET #Q2 = 'FROM [TestDatabase].[details] WHERE id ' + '=''' + CAST(#id AS VARCHAR(10)) + '''';
SET #Q3 = #Q1 +' '+ #Q2
PRINT #Q3
EXEC sp_executesql #Q3
Tried 'How to get sp_executesql result into a variable?' and not able to get the results.
Assuming that you get a singleton value from your dynamic statement:
DECLARE #ID int, --Is set somewhere
#YourVariable nvarchar(30), --Use an appropriate data type
#formfieldpath sysname; --Is set somewhere
DECLARE #SQL nvarchar(MAX);
--I assume that the name [TestDatabase].[details] is wrong, as [TestDatabase] would be the name of the schema, not the database,
--and I ASSUME you haven't foolishy created a schema called "TestDatabase"
SET #SQL = N'SELECT #YourVariable = ' + QUOTENAME(#formfieldpath) + N' FROM dbo.Details WHERE id = #id';
--Use the correct datatype for #YourVariable
EXEC sys.sp_executesql #SQL, N'#id int, #YourVariable nvarchar(30) OUTPUT', #id, #YourVariable OUTPUT;
Never inject unsanitised values into a dynamic SQL statement. SQL injection is a huge problem that should have stopped existing over a decade ago. Dos and Don'ts of Dynamic 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);

Dynamic sql with output parameter syntax clarity needed

I've read several examples of how to return an output parameter with dynamic sql, but all were slightly different in that they created the variable within the procedure, instead of passing them in (I'm assuming this is the root of my problem). I get the error:
Must declare the table variable "#tbl".
When I try to run the procedure below (listed after the test code that executes it). Am I close?
DECLARE #tbl nvarchar(40)
DECLARE #bnch INT
SET #tbl = 'tblDailyPricingAndVol'
EXEC sprocReturnDataPointBenchmark #tbl, #bnch
sproc:
ALTER PROCEDURE [dbo].[sprocReturnDataPointBenchmark] #tblName NVARCHAR(50),
#benchmark BIGINT OUTPUT
AS
BEGIN
DECLARE #sql nvarchar(1000),
#parameters NVARCHAR(100) = N'#tbl NVARCHAR(50), #benchOUT BIGINT OUTPUT';
SET #sql = N'SELECT #benchOUT = Count(ID) FROM #tbl WHERE DateAdded = ' +
'(SELECT MAX(DateAdded) FROM tblDailyATR AS T2)';
EXEC sp_executesql #sql, #parameters, #tbl = #tblName, #benchOUT = #benchmark OUTPUT
SELECT #benchmark
END
There were a couple syntactical errors in my first pass listed above, but the conceptual issue that I needed to resolve was trying to pass the table name (input parameter) in the parameters variable within the dynamic sql. Good example here: Generate dynamic SQL statements in SQL Server
So, my revised, working code is:
ALTER PROCEDURE [dbo].[sprocReturnDataPointBenchmark] #tblName NVARCHAR(50),
#benchmark BIGINT OUTPUT
AS
BEGIN
DECLARE #sqlStatement nvarchar(500)
DECLARE #parameters NVARCHAR(100)
DECLARE #fullStatement NVARCHAR(500)
SET #parameters = '#benchmark BIGINT OUTPUT'
SET #sqlStatement = N'SELECT #benchmark = Count(ID) FROM ' + #tblName + ' WHERE DateAdded = ' +
'(SELECT MAX(T2.DateAdded) FROM ' + #tblName + ' AS T2)';
EXEC sp_executesql #sqlStatement, #parameters, #benchmark = #benchmark OUTPUT
SELECT #benchmark
END

Getting error while export data from excel

I am getting following error
ERROR:- Incorrect syntax near '+'.
while executing following T-Sql
DECLARE #DatabasePath VARCHAR(MAX)
SET #DatabasePath = 'E:\ABC.xls'
INSERT INTO [dbo].[Table_1]
SELECT *
FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0',
'Excel 8.0;Database='+#DatabasePath+'',
'SELECT * FROM [Sheet1$]') AS xlsTable
Is there something wrong in T-Sql.
Actually i want to create a stored procedure where i will pass excel sheet path in #DatabasePath input parameter.
I dont thing this will work for you.
From OPENROWSET (Transact-SQL)
'datasource'
Is a string constant that corresponds
to a particular OLE DB data source.
Have you tried something like
DECLARE #DatabasePath VARCHAR(MAX)
SET #DatabasePath = 'C:\tada.xlsx'
DECLARE #RowSetString VARCHAR(MAX)
SELECT #RowSetString = 'SELECT * FROM OPENROWSET(''Microsoft.Jet.OLEDB.4.0'',''Excel 8.0;Database=' + #DatabasePath + ''',''SELECT * FROM [Sheet1$]'')'
SELECT #RowSetString
EXEC(#RowSetString)
You will need to use dynamic SQL:
DECLARE #DatabasePath VARCHAR(MAX)
SET #DatabasePath = 'E:\ABC.xls'
DECLARE #sql nvarchar(MAX)
SET #sql = '
INSERT INTO [dbo].[Table_1]
SELECT *
FROM OPENROWSET(''Microsoft.Jet.OLEDB.4.0'',
''Excel 8.0;Database=' + #DatabasePath + ',
''SELECT * FROM [Sheet1$]'') AS xlsTable'
EXEC sp_executesql #sql