Concatenated SQL statement - sql

I'm working on a query that builds a list of table names from the sys.database master table. I then use those name in a concat statement to pull a specific piece if information out of each database. I'm running the whole thing through a while loop to hit all tables, with a counter.
i.e.
set #sql = 'select top 10 * from ' + (select dbname from #table where tabid = #i + '.dbo.**tablename** where NAME = '**String Value**'
When I just print the results of #sql, it gives me the correct syntax, and I am able to run the command with no problem.
When I set #sql to exec, I get an error
"database select top 10 * from dbname does not exist."
It's like the execute is ignoring everything after the select.

I'm suspecting you're calling EXEC incorrectly.
When calling 'exec' with a T-SQL query, be sure to enclose the target string in parenthesis, eg
DECLARE #FOO VARCHAR(100)
Set #FOO = 'SELECT TOP 5 * from SOMETABLE'
EXEC (#FOO) -- not EXEC #FOO

Related

Why is the openquery returning 0 rows on SQL server but has 900k rows in the target Server?

Need help to figure ut why the remote query I execute on the server return 0 rows , but the same query returns over 900k rows in the target DB.
the string is less 8000 characters long so I won't post it here. but this is the sctructure basically:
declare #SQL varchar(MAX);
declare #D varchar(15);
declare #Per varchar(15);
declare #NextPer varchar(15);
declare #NextYPer varchar(15);
set #D = N'01-JUN-2019'
set #Per = N'2020004';
set #NextYPer = N'2021004'
set #NextPer = N'2020005'
set #SQL = N' SELECT ...... '
set #SQL = N'select * from openquery ([LK1], "'+#SQL+'")';
execute( #SQL);
print #SQL;
Note: the linked server works and is used on other openqueries with shorter strings successfully. I tried using EXECUTE (#SQL) AT and I still get 0 rows. When i exexute the print output directly on the Oracle DB , the query runs for about 15 min and gives results.
First off, OPENQUERY requires the second parameter to be a query string. A string in SQL Server is written between single quotes. From OPENQUERY documentation:
OPENQUERY ( linked_server ,'query' )
Not only that, the SQL that appears in that string, needs to have any single-quotes that appear in the query to be doubled. Suppose you had SQL you wanted to execute the following query:
SELECT * FROM some_table WHERE name='TT.';
You would write this as:
OPENQUERY(lks,'SELECT * FROM some_table WHERE name=''TT.''')
But if you have this in a dynamic SQL statement, this would become
DECLARE #s VARCHAR(MAX);
SET #s='SELECT * FROM OPENQUERY(lks,''SELECT * FROM some_table WHERE name=''''TT.'''''')';
So that's some explosion of single quotes for even the more trivial SQL queries. Count ye quotes, make sure the query itself is up to snuff (i.e. quotes have been properly doubled).
Thanks all for the input.
The root cause is simply the format of the Date parameter, which didn't run correctly on the linked server.
All I had to do is change my query to use this:
SO_BOOK_DATE < to_date(''#D'' , ''DD-MON-YYYY'')
instead of
SO_BOOK_DATE < ''#D'' .

Scalar variable must be declared in SQL variable

I'm creating a report using sql scripts through management studio and I'm getting the error " Must Declare the scalar variable "#Account". I've been reading other similar questions on this portal but they are related to c#
I'm currently trying to reduce the code on the script so I decided to put a sql script into a variable because depending on a condition the where condition will change. Below is an example of the code
Declare #Account int = 1 , #SQL varchar(max)=''
Select #SQL = N'Select ColumnA,ColumnB, ColumnC from Table1 where ColumnA =1'
if #Account IS NULL
Begin
exec(#SQL)
end
--Here is where the error is hapening
else
begin
--This is the line causing the error
Select #SQL = #SQL + 'AND ColumnB=#Account"
exec(#SQL)
end
If I type manually the value of the variable next to "ColumnB=" it works but the account number will be selected by the user executing the script. I'm thinking on maybe building a temp table to capture the variable value and then do a sub query on the where condition but maybe the solution to this error may be more easier
You want sp_executesql:
select #SQL = #SQL + 'AND ColumnB=#Account';
exec sp_executesql #SQL, N'#Account int', #Account=#Account;
This is how you pass parameters into a dynamic SQL statement in SQL Server. I strongly recommend that you only use sp_executesql to execute SQL statements -- even when you don't have parameters. Using it makes it easy to implement parameters when you need them.
You are passing in '#Account' into the #SQL variable -- the underlying EXEC cannot see that variable.
One way of fixing this would instead be to do this:
Select #SQL = #SQL + 'AND ColumnB=' + CAST(#Account as varchar)

OPENQUERY(SERVERNAME, STOREDPROCEDURE) Syntax error

This is my code
DECLARE #stringvariable nvarchar(200) = 'Hello';
DECLARE #sql nvarchar(2000) = SELECT * INTO ##global FROM OPENQUERY(DB1, ''EXEC GETCASE ''' + #stringvariable + ''''')'
Printing #sql returns a correctly formatted query, however SQL Server doesn't like #stringvariable and returns an error
Msg 102, Level 15, State 1, Line 11
Incorrect syntax near 'Hello'.
Here is what the outputted query looks like
SELECT * INTO ##global FROM OPENQUERY(DB1, 'EXEC GETCASE 'Hello'')
How can I avoid this error? It seems like because my stored procedure takes a string parameter, it's throwing off the query. I've read that OPENQUERY does not support variables, but I've parameter the variable so it should work?
Appreciate your help!
The stored procedure exists in a database and a schema. You need to supply those. Supposing database db_name and schema schema_name:
DECLARE #stringvariable nvarchar(200) = 'Hello';
SET #stringvariable=REPLACE(#stringvariable,'''',''''''''''); -- doubly doubled single quotes for the dynamic statement
DECLARE #sql nvarchar(2000) = 'SELECT * INTO ##global FROM OPENQUERY(DB1, ''SET FMTONLY OFF;EXEC db_name.schema_name.GETCASE ''''' + #stringvariable + ''''''')';
I've also made sure single quotes are properly escaped in the #stringvariable.
It's also likely you need to start the query with SET FMTONLY OFF; so I've added that.
Update: To test this I created following simple procedure on a linked server local_server in database TEST_TT
CREATE PROCEDURE [dbo].[tst]
#i VARCHAR(128)
AS
SELECT #i AS field;
I then ran the following:
DECLARE #var VARCHAR(128)='TT.';
SET #var=REPLACE(#var,'''',''''''''''); -- doubly doubled single quotes for the dynamic statement
DECLARE #stmt VARCHAR(4000)='SELECT * INTO ##tt FROM OPENQUERY(local_server,''SET FMTONLY OFF;EXEC TEST_TT.dbo.tst '''''+#var+''''''');';
EXEC (#stmt);
SELECT * FROM ##tt;
DROP TABLE ##tt;
And I received the results. I count 7 (!!) single quotes at the end of the query... yuck! Updated original part with the same number of quotes.

SQL Server stored procedure passing parameters into variables

I have a big query which works and I want to write a stored procedure for it.
I'm getting this error:
the OLE DB provider SQLNCLI11" for linked server "theServer" does not contain the table ""#dbName"."dbo"."tableName"
What I am trying to do:
create PROCEDURE [sys.sp_myProcedure]
(
#dbName varchar(30) output,
#rid varchar (10) output,
#mdate output
)
AS
BEGIN
declare #prt varchar(12)
declare #pid int
declare #cid int
--declare #rid int
declare #aid int
SET NOCOUNT ON;
set #cid= (select CID from theServer.[#dbName].dbo.tableName where RID= #rid)
set #pid= (select PID from theServer.[#dbName].dbo.tableName where RID= #rid)
set #aid= (select aid from theServer.[#dbName].dbo.tableName where RID= #rid)
--then my query begins
theServer.[#dbName].dbo.tablename is a linked server.
What I want to do is:
execute [sys.sp_myProcedure] 'someDbname', '123', '2012-03-03'
and the parameters passed here would set/update the variables #dbName, #rid, #mdate at runtime. ( #mdate I have it further away in the query, it's too big to adapt it with myTable and to change all the sensitive data).
How can I do this ?? (using SQL Server 2012)
edit (based on the comments and answers):
so, it's #thatString = '--insert the query here ' . Then, in my case how can i set those variables according to the parameters inside the query? Should i do it with replace? like this: set #thatString= replace(#thatString, dbName, #dbname) ?
**
edit 2
**
set #sql = '
use [someDbName];
use [123];
use [2012-03-03];
select ... '
set #sql = replace (#sql, 'someDbName', #dbName)
set #sql = replace (#sql, '123', #rid)
set #sql = replace (#sql, '2012-03-03', #mdate)
execute #sql
end
Did i get it right? is the execute #sql in the right place?
I'm asking cause it doesnt work. i'm getting the name ' --part of my query here' is not a valid identifier
Names of databases or other objects cannot be specified dynamically from variables. The workaround is to compose a dynamic SQL query in a string, into which you concatenate the required names, and then execute (#thatString).
(You might think you can employ use, but it is scoped such that you would have to include the rest of your query within the same executed string.)
--
Edit with more info as requested. You can compose the string however you like. If you need any more guidance, there are plenty of pages that discuss dynamic T-SQL. But hey, two ideas:
set #myDynamicQuery =
'
use [' + #myDynamicDatabase + '];
select BLAH from WHOM where DATA = ''what'';
';
or if you will be using the name a lot, you could reduce the hassle caused by breaking in and out of single quotes as follows - though I personally never use this as I don't like how it looks:
set #myDynamicQuery =
'
use [A_RARE_PLACEHOLDER];
select BLAH from WHOM where DATA = ''what'';
-- lots more uses of A_RARE_PLACEHOLDER
';
set #myDynamicQuery = replace(
#myDynamicQuery,
'A_RARE_PLACEHOLDER',
#myDynamicDatabase
);
Then execute (#myDynamicQuery);

How can I get tables name from sys.tables and store the output in a variable?

I have written a stored procedure where a table name and database name collect
using cursor from different two tables.
But my problem is when I run a query to find out a table exists in a database or not, then show a error.
Now how can I run the query and store output into a variable?
Declare #table_exist nvarchar(200),#val1 nvarchar(200),#return1 nvarchar(200);
SET #table_exist=
'SELECT 1 FROM '+#db_name+'.sys.tables
where name='+#table_name+'';
EXEC sp_executesql #table_exist,#return1 OUTPUT;
select #return1;
ERROR:
Invalid column name 'table name'
You should use quotename when building dynamic query:
SET #table_exist=
'SELECT 1 FROM '+ quotename(#db_name)+'.sys.tables
where name='+quotename(#table_name)+'';
When facing such an error the best would be to print #table_exists and see what is actually built.
I haven't looked properly at your query. You are missing apostrophes:
SET #table_exist=
'SELECT 1 FROM '+ quotename(#db_name)+'.sys.tables
where name=''' + #table_name +'''';
UPDATE:
When using output variable you should set it in a query:
SET #table_exist=
'SELECT #return1 = 1 FROM ' + quotename(#db_name) + '.sys.tables
where name='''+#table_name+'''';
To prevent result set from returning to client, create temporary table and insert result set into it. In this case this will leave only one result set, the result of select #return1:
declare #tbl table (exist bit)
insert into #tbl
EXEC sp_executesql #table_exist, N'#return1 nvarchar(200) out', #return1 OUT;
select #return1;
It is best to write your query by using ' and " properly . Which makes less mistakes while writing query.
The error on you code is that you are confused by using only '. Best to use ' for variable only.
Write your code as:
"SELECT 1 FROM ' "+#db_name+" '.sys.tables
where name=' "+#table_name+" ' ";