Execute very long statements in TSQL using sp_executesql - sql-server

I would like to execute dynamic SQL statements which are about 10,000 characters.
When I use sp_executesql as below:
DECLARE #stmt varchar(MAX)
SET #stmt = 'xxxxxxxx.................' which is about 10,000 characters
EXEC sp_executesql #stmt
I got the following error
The character string that starts with ' select t1.e_reference xxxxxxxxxxx' is too long. Maximum length is 8000.
As far as I know, we can use sp_executesql to execute very long statements, can't we?
I am using SQL Server 2008, Enterprise Edition, 64 bit.
How can I achieve this? Thanks.

Based on your responses in the post, you are using linked server.
The 8000 char limit is not posed by sp_executesql, but by OPENQUERY that you are probably using in your variable #stmt .
MSDN says this of OPENQUERY's arguments:
'query' Is the query string executed in the linked server. The maximum
length of the string is 8 KB.
http://msdn.microsoft.com/en-us/library/ms188427.aspx
To bypass this, you could probably use
execute (#query) at oracle_linked_server

MSDN says this which is a bit vague:
"The size of the string is limited only by available database server memory. On 64-bit servers, the size of the string is limited to 2 GB, the maximum size of nvarchar(max)."
On 64-bit servers the limit is 2GB. It is not clear what is the limit of 32-bit servers? Is it 4000, 8000, whatever memory is available, 2GB?

The #stmt parameter for sp_executesql has a data type of nvarchar(8000), so you have exceeded the limit.
Either refactor your SQL statements into smaller parts, or put the SQL into a stored procedure.

Related

Dynamic SQL Statement is too long

I am using quite a long dynamic SQL Statement (a bit more than 13000 characters) but when I am trying to execute it, I am noticing that the exec isn't reading the statement completly and cuts the last part off.
I am using:
DECLARE #Statement nvarchar(max)
SET #Statement = N'[LONG STATEMENT]'
EXEC (#Statement)
I did notice, that it could read even less characters, if I am not using the the brackets in EXEC (#Statement)
I also tried using EXEC sp_executesql #Statement
It just stops reading the statement after 12482 characters...
I have the problems with SQL-Server 2008 R2 and SQL Server 2014
EDIT: OK, now I noticed something different. It seems, that the lenght itself of the statement is not exactly the problem. As I mentioned in a comment below, I am using this long dynamic sql statement, because I am creating an update script, which adds a new stored procedure and within this procedure I am using table names, which can differ. So I created variables, which contain the table names and used these variables with the dynamic sql statement, so I don't need to change the table names within the procedures and functions I am adding with this update script, but just changing the content of the variables.
However, if I am NOT using these variables and use the table names "hardcoded" in the statement, the statement can be executed successfully...
I guess the answer is here:
So I created variables, which contain the table names and used these
variables with the dynamic sql statement, so I don't need to change
the table names within the procedures and functions I am adding with
this update script, but just changing the content of the variables.
I guess, your dynamic T-SQL statement is built using string concatenation. So, let's say we have something like this:
DECLARE #DynamicSQLSTatement NVARCHAR(MAX);
DECLARE #TableName01 NVARCHAR(128) = 'T01';
DECLARE #TableName02 NVARCHAR(128) = 'T02';
DECLARE #TSQL NVARCHAR(4000) = REPLICATE(N'X', 4000);
SET #DynamicSQLSTatement = #TableName01 + #TSQL + #TableName02;
We have three short strings (length < max) and when they are concatenated, we expect that the new NVARCHAR(MAX) value will be capable of storing the whole new string (it is with max length, after all).
So, the following statement will give as T02, right?
SELECT RIGHT(#DynamicSQLSTatement, 3);
But no, the output is XXX. So, the question is why the whole concatenation text is not preserved?
When you are concatenating nvarchar(1-4000) strings they output string is not converted to max if it is not possible to store all the data.
In order to fix this, we can cast the first part of the string to nvarchar(max):
SET #DynamicSQLSTatement = CAST(#TableName01 AS NVARCHAR(MAX)) + #TSQL + #TableName02
SELECT RIGHT(#DynamicSQLSTatement, 3);
I'd imagine your hitting a limit of about 16K (8K used to be the most data you could hold in a variable before nvarchar(max) etc was invented. You could try using varchar(max) instead of nvarchar as that will be half the size (unicode is 16-bit, ascii is 8-bit). I have a feeling that won't help much though.
Really though, you're hitting this issue because whatever you're trying to do shouldn't really be done like that, super long SQL statements are a sign that you've gone down the wrong path. Find a way to break down your query or operations. If this is a query, consider if you could restrict your data set over a few steps rather than in one query.

Equivalent to sp_executesql in Sybase

What's the equivalent to sp_executesql of Sql Server in sybase.
I think exec() is what you're looking for. See http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.ase_15.0.commands/html/commands/commands56.htm.
#jasir: the limitation to 255 characters results from your procedure definition. Isn't possible to extend this limit by defining e.g. varchar(1024)?
ASE Refrence Manual 15.7 (http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc36272.1572/html/commands/X30305.htm)
states for command execute:
string is a literal string containing part of a Transact-SQL command
to execute. There are no restrictions to the number of characters
supplied with the literal string.
However, sometimes a system on top of sybase (e.g. Kondor+, a product for financial markets uses ASE 15.x as DB) may set limits. In this Kondor+ it is not possible to use
exec( #SQLQuery)
in its so called OpenReport (a stored procedure), if the variable #SQLQuery exceeds 256 characters.
For older ASE, you can use this workaround:
There is stored procedure sp_remotesql.
You can use it to run query on local server too, you just have to local server to servers:
sp_addserver local, NULL, <servername>
Where <servername> is name of local server (from sql.ini).
You can add shortcut procedure for running sql:
create procedure sp_exec_dynsql #p_cmd varchar(255)
as
begin
exec sp_remotesql "local", #p_cmd
end
Unfortunatelly, you are limited to 255 characters in your sql.

SQL Server / SSIS - Dynamic T-SQL, NVARCHAR(MAX) Difference

I am writing some dynamic SQL:
DECLARE #sql NVARCHAR(MAX)
SET #sql = '...'
EXEC sp_executesql #sql
If I execute this from SSMS, the query executes successfully because it is less than 8000 (7787 to be precise) characters. If I execute this from SSIS (using an ADO.NET connection) the query fails because NVARCHAR(MAX) is the equivalent of NVARCHAR(4000).
I understand this is something to do with compatibility - the connection from SSIS needs to support more than just SQL Server.
What are my workaround options?
For me, I'd go this way (in order of preference):
Find a way to do it without using dynamic SQL (such a large dynamic script must be a nightmare to debug or change)...
Split some of it out into stored procedures and call those from your dynamic SQL.
Split it into a number of smaller sub queries.

Use of '' + in SQL Server 2005 Stored Procedure to build SQL string

I'm building a stored procedure which is rather stretching my experience. With the help of people who responded to this thread [Nested if statements in SQL Server stored procedure SELECT statement I think I'm most of the way there :)
In short, the SP takes a series of paramterised inputs to dynamically build an SQL statement that creates a temporary table of id values ordered in a specific way. The remainder of the SP, which returns the data according to the requested page from the id values in this temporary table is all sorted.
Reconsider the use of dynamic SQL - you should really know what you are doing if you go that route.
What is the problem you are trying to solve? I am sure people here will be able to find a better solution than the dynamic SQL you are proposing to use.
Take a look at CONVERT() and CAST() for the integers.
To concatenate integer values into the dynamic SQL statement you need to convert to a varchar e.g:
....WHERE
OT.site_id = ' + CAST(#siteid AS VARCHAR)
If the SQL statement is always going to be less than 4000 chars, I'd at least consider using sp_executesql to use parameterised SQL.
e.g.
DECLARE #SQL NVARCHAR(4000)
DECLARE #siteid INTEGER
SET #siteid = 1
SET #SQL = 'SELECT * FROM MyTable WHERE site_id = #siteid'
EXECUTE sp_executesql #SQL, N'#siteid INTEGER', #siteid
All in all, what you're doing is not likely to be very performant/scalable/maintainable and you don't really gain much from having it as a sproc. Plus you need to be very very careful to validate the input as you could open up yourself to SQL injection (hence my point about using sp_executesql with parameterised SQL).
You need to cast the int param to be a char/varchar so that you can add it to the existing string. The fact that you aren't surrounding it with quotes in the final sql means it will be interpreted as a number.

how to set 9000 characters in nvarchar(max)

I need to set 9000 characters in nvarchar variable
declare #inXMLRequest xml
declare #insertsql nvarchar(max)
set #insertsql='--------9000 characters--------'
EXEC sp_executesql #insertsql,
N'#inXMLRequest XML OUTPUT',
#inXMLRequest OUTPUT
print #insertsql
But NVARCHAR is taking 5000 characters only
how to set 9000 characters in NVARCHAR variable?
if you write a small program that tries the same thing outside the management studio you will be able to do this.
unfortunately for some reason it is not possible to do this with a insert statement in the management studio. there is a 4k limit on what you put into the management studio.
I've people do inserts before, ie, first insert 4k chars then the next 4k chars etc
I'm not sure, but you cant store such long rows in varchar.
a row have to fit into a db-page.
varchar fields are stored in the same page, where the row is stored.
a page is usually smaller than 8192 bytes (depending on db-system)
there a some exceptions like blob fields which are not stored in the same page of a row.
you should use a other data type like text/blob/image.
nvarchar 9000 is btw. impossible this will allocate 18000 byte which dont fit into a page.
this is the reason for the 4000 char limit.
Thanks to All,
Insted of using SP_Executesql directly we Executing nvarchar variable
Above we Are preparing #insertsql nvarchar variable morethan 8000 characters and it is giving to sp_executesql like this
EXEC sp_executesql #insertsql, N'#inXMLRequest XML OUTPUT',#inXMLRequest OUTPUT
insted of above query replaced with below query
Exec ('DeClare #inXMLRequest XML SET #inXMLRequest='------above 8000 characters---')
Finally we will execute that nvarchar string and get out put

Resources