SELECT #SqlCmdEnd =',Member_Cd as x_Member_Cd,
LOD.Val_Seq as x_GroupSort,
vs.Member_RCID as x_Org_Key,
LOD.Val_Cd as x_Level_Text,
Type_RCID as x_Type_RCID
into ##VS_Wide'+#l_Random+'
We have a dynamic query inside a stored procedure which uses a global temp table as shown above. It is working fine for normal scenarios but during load, concurrency test we are getting an error:
Invalid object ##VS_Wide12345
12345 is a random number generated using the below script.
So what could be the possible reason for this error? Any help on this will be appreciated.
select #l_Random = replace(right(rand(), 5), '.', '')
Try this one -
DECLARE #l_Random CHAR(32) = REPLACE(NEWID(), '-', '')
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = '
IF OBJECT_ID(''##VS_Wide' + #l_Random + ''') IS NOT NULL
DROP TABLE ##VS_Wide' + #l_Random + '
SELECT 1 AS a
INTO ##VS_Wide' + #l_Random + '
SELECT * FROM ##VS_Wide' + #l_Random + '
'
PRINT #SQL
EXEC sys.sp_executesql #SQL
Output -
IF OBJECT_ID('##VS_WideC016ADF003FD4254B6BBFB5053E9C956') IS NOT NULL
DROP TABLE ##VS_WideC016ADF003FD4254B6BBFB5053E9C956
SELECT 1 AS a
INTO ##VS_WideC016ADF003FD4254B6BBFB5053E9C956
SELECT * FROM ##VS_WideC016ADF003FD4254B6BBFB5053E9C956
Related
DECLARE #SQLSTRING VARCHAR(1500);
DECLARE #TABLENAME1 VARCHAR(30)='NOV19_COMBINE'
---------------TABLE CREATION WITH FILE NAME--------------------------
SET #SQLSTRING = 'SELECT
CONVERT(VARCHAR('+ cast((select max(len(EMAIL)) from '+#TABLENAME1+' ) as VARCHAR(50))+'), EMAIL ) AS EMAIL,
IDENTITY (INT,1,1) AS RECORDID
INTO FOI_'+#TABLENAME1+'_CONV
FROM '+#TABLENAME1+' A'
PRINT #SQLSTRING
Error:
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near '+#TABLENAME1+'.
You have an issue here:
CONVERT(VARCHAR('+ cast((select max(len(EMAIL)) from ' + #TABLENAME1 + ' ) as VARCHAR(50))+')
where you are trying to select from a table defined in #TABLENAME1. That also needs to be part of your dynamic SQL.
However you have another issue with your convert(varchar( code in that you cannot use a variable as as the length to varchar(). I suggest using varchar(max) because that only uses the storage required.
I have also made your dynamic SQL safe from injection with the use of QUOTENAME which I recommend you use in future.
Fixed version:
DECLARE #SQLSTRING VARCHAR(1500);
DECLARE #TABLENAME1 VARCHAR(30) = 'NOV19_COMBINE'
---------------TABLE CREATION WITH FILE NAME--------------------------
SET #SQLSTRING = 'SELECT CONVERT(VARCHAR(max), EMAIL) AS EMAIL, IDENTITY (INT,1,1) AS RECORDID INTO '
+ QUOTENAME('FOI_' + #TABLENAME1 + '_CONV') + ' FROM '
+ QUOTENAME(#TABLENAME1) + ' A'
PRINT #SQLSTRING
There is no reason I can think of to do it this way, but as an academic exercise, if one really needed the exact length of the EMAIL column then one would use the following query:
declare #SQLSTRING nvarchar(max), #TABLENAME1 VARCHAR(30) = 'NOV19_COMBINE', #EMAILLENGTH int
SET #SQLSTRING = 'SELECT #Length = max(len(EMAIL)) from ' + QUOTENAME(#TABLENAME1)
EXECUTE sp_executesql #SQLSTRING, N'#Length int OUTPUT', #Length = #EMAILLENGTH OUTPUT
SET #SQLSTRING = 'SELECT CONVERT(VARCHAR(' + convert(varchar(4),#EMAILLENGTH) + '), EMAIL) AS EMAIL'
+ ', IDENTITY (INT,1,1) AS RECORDID'
+ ' INTO ' + QUOTENAME('FOI_' + #TABLENAME1 + '_CONV')
+ ' FROM ' + QUOTENAME(#TABLENAME1) + ' A'
PRINT #SQLSTRING
This requires 2 sections of dynamic SQL, the first to find the length of the EMAIL column, which is then used to built the dynamic SQL for the actual query.
Really wrecking my head here and as with many sql mess up I know it is probably something silly and stupid but I just cant seem to get it to work.
I have a stored procedure which is this..
ALTER PROCEDURE [dbo].[RETURN_DATA](#TABLE_param VARCHAR(7),#COUNTRY_param VARCHAR(2),#FILEDATE_param int,#TTKT_param VARCHAR(6))
AS
BEGIN
SET NOCOUNT ON;
SELECT #SQL = 'Select * from ' + #TABLE_param + ' WHERE COUNTRY = ' + #COUNTRY_param + ' AND MONTH(Fil_Dte) = ' + cast(#FILEDATE_param as varchar(20)) + ' AND TRNN = '+ #TKTT_param
EXECUTE(#SQL)
END
I'm using it in a vb.net windows form app so applying the parameters there. But trying to run it in SSMS with this
exec RETURN_DATA #COUNTRY_param='GB',#FILEDATE_param=4,#TABLE_param='table30',#TTKT_param='000000'
Returns the error
Invalid column name 'GB'. which i find strange as I never called for a column called GB but called for rows with GB in the column COUNTRY in my where clause?
I know this hopefully is a simple fix so any help would be greatly appreciated and also even if you think theres a better way to go about writing the SP!
Thanks in advance guys.
I'd recommend parameterising the SQL which will guard against SQL injection and you don't have to worry about escaping quotes as below
ALTER PROCEDURE [dbo].[RETURN_DATA](#TABLE_param VARCHAR(7),#COUNTRY_param VARCHAR(2),#FILEDATE_param int,#TTKT_param VARCHAR(6))
AS
BEGIN
SET NOCOUNT ON;
SELECT #SQL = 'Select * from ' + #TABLE_param + ' WHERE COUNTRY = ''' + #COUNTRY_param + ''' AND MONTH(Fil_Dte) = ' + cast(#FILEDATE_param as varchar(20)) + ' AND TRNN = '''+ #TKTT_param +''''
EXECUTE(#SQL)
END
Use sp_executesql to run dynamic sql
DECLARE #SQL NVARCHAR (4000);
SET #SQL = '
Select *
from ' + QUOTENAME(#TABLE_param) + '
WHERE COUNTRY = #COUNTRY_param
AND MONTH(Fil_Dte) = #FILEDATE_param
AND TRNN = #TTKT_param
';
EXEC sp_executesql #SQL,
N'#COUNTRY_param VARCHAR(2), #FILEDATE_param int, #TTKT_param VARCHAR(6)',
#COUNTRY_param, #FILEDATE_param, #TTKT_param;
sp_executesql
I am trying to dynamically insert data into a temp table passing like data as a variable:
DECLARE #data NVARCHAR(MAX)
SET #data = 'INSERT INTO #coco ' + '([' + #val + '])' + ' SELECT [USER_ID] FROM [dbo].[Sheet1$] WHERE [Standard_Name] LIKE ' + #val
EXEC sp_executesql #data
#val is a column name selected from table Sheet1$ and few column name has space between them. While executing, I am getting error, like for column name "Acrobat Reader":
Incorrect syntax near 'Acrobat'.
Also if I am adding data using hardcoded one by one in a column its adding data to one column while other column its adding NULL.
Any suggestion how I can overcome this?
Parametrise your SQL, and this problem "goes away":
DECLARE #data;
SET #data = N'INSERT INTO #Coco (' QUOTENAME(#val) + N')' + NCHAR(10) +
N'SELECT [USER_ID]' + NCHAR(10) +
N'FROM dbo.[Sheet1$]' + NCHAR(10) +
N'WHERE [Standard_Name] = #val;'; --As this doesn't contain a %, there's no need for LIKE
EXEC sp_executesql #data,
N'#val = sysname', --guessed datatype
#val = #val;
Note the comments I made in the SQL though.
Afraid, I've no idea what your second statement means. You'll need to explain further.
We have a stored procedure built using dynamic sql where our application passes in some column names. Occasionally blank or null values are passed through for the column name. In these cases the sp needs to return a null value for the column. I've tried various ways of handling this but whatever I do I seem to get the error below:
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name.
Here is an example query with case when trying to handle null column names in the #Col2 param:
DECLARE
#Col1 varchar(32) = 'name',
#Col2 varchar(32) = '',
#sqlCommand nvarchar(MAX) = ''
SET #sqlCommand = #sqlCommand + N'
SELECT ' + quotename(#Col1) + ' AS ' + quotename(#Col1) + ',
CASE WHEN ' + quotename(#Col2) + ' IS NULL OR ' + quotename(#Col2) + ' = ''''
THEN NULL
ELSE ' + quotename(#Col2) + '
END AS Col2
FROM sys.columns c '
EXECUTE sp_executesql #sqlCommand
Solution
DECLARE
#Col1 varchar(32) = 'name',
#Col2 varchar(32) = '',
#sqlCommand nvarchar(MAX) = ''
SET #sqlCommand = #sqlCommand + N'
SELECT ' + quotename(#Col1) + ' AS ' + quotename(#Col1) + ',' +
CASE WHEN #Col2 IS NULL OR #Col2 = ''
THEN 'NULL '
ELSE quotename(#Col2)
END + ' AS Col2
FROM sys.columns c '
--print #sqlCommand
EXECUTE sp_executesql #sqlCommand
Notes
When you have an issue with Dynamic SQL, try using the Print statement to output the generated command to SSMS (or if you're not using SSMS, find some other way to pull back the generated SQL so you can see what's going on.
Doing this with your original code shows that the statement generated was:
SELECT [name] AS [name],
CASE WHEN [] IS NULL OR [] = ''
THEN NULL
ELSE []
END AS Col2
FROM sys.columns c
... which you can probably see the issue with.
The problem was that you got confused between the SQL you were using to generate the Dynamic SQL, and the SQL required to be part of the Dynamic SQL statement being returned.
I'm trying to execute an inline SQL statement within a stored procedure. I'm working with SQL Server 2008.
The problem is that I can't execute the first inline statement (with WHERE clause). It crashes because the string within EXEC(...) is dynamically created and all concatenated variables must be of type varchar.
Error that appears when calling procedure:
An expression of non-boolean type specified in a context where a
condition is expected, near 'ORDER'.
The procedure looks like:
CREATE PROCEDURE loadMyRows
#table_name nvarchar(50),
#bounding_box varchar(8000)
AS
BEGIN
-- *********************************** COMMENT *********************************
-- ** This two code lines are correct and will return true (1) or false (0), **
-- ** but they doesn't work within inline EXEC(...) **
--DECLARE #bb geometry = geometry::STGeomFromText(#bounding_box, 4326);
--select TOP(5) wkt.STWithin(#bb) AS 'bool'
-- *********************************** COMMENT *********************************
IF #bounding_box <> ''
BEGIN
DECLARE #bb geometry = geometry::STGeomFromText(#bounding_box, 4326);
EXEC(
'SELECT TOP (' + #row_limit + ') * ' +
'FROM ' + #real_table_name + ' ' +
'WHERE wkt.STWithin('+#bb+') ' + -- <-- doesn't work :-(
-- 'WHERE wkt.STWithin(geometry::STGeomFromText('''+#bounding_box+''', 4326)) ' +
-- ^^ doesn't work, too :-(
'ORDER BY id ASC '
);
END
ELSE
BEGIN
EXEC(
'SELECT TOP (' + #row_limit + ') * ' +
'FROM ' + #real_table_name + ' ' +
'ORDER BY id ASC'
);
END
END
I've found a working solution for this problem. The way the MSDN showed me was http://msdn.microsoft.com/en-US/library/ms175170.aspx. There's written:
[...] the string is executed as its own self-contained batch.
That let me know, if I want to execute a dynamic statement with a table variable as string, it's the same as I would execute the query without the EXECUTE command, like:
SELECT TOP(#row_limit) *
FROM #real_table_name
WHERE ...
ORDER BY id ASC;
And this would probably not work for the table name.
So, if I write instead:
DECLARE #sql_statement nvarchar(MAX) = 'SELECT TOP(#limit) *
FROM ' + #real_table_name + '
ORDER BY id ASC';
-- declaration of parameters for above sql
DECLARE #sql_param_def nvarchar(MAX) = '#limit int';
EXECUTE sp_executesql #sql_statement, #sql_param_def, #limit = #row_limit;
Then, this would work. This is because I define the #sql_statement simply as a concatenated string which will just resolve the dynamic table name at runtime to a string with the name of the real existing table. The #limit parameter is untouched and is still a parameter.
If we then execute the batch we only must pass a value for the #limit parameter and it works!
For the geometry parameter it works in the same way:
DECLARE #bb geometry = geometry::STGeomFromText(#bounding_box, 4326);
SET #sql_statement = 'SELECT TOP(#limit) *
FROM ' + #real_table_name + '
WHERE wkt.STWithin(#geobb) = 1
ORDER BY id ASC';
-- NOTE: This ' = 1' must be set to avoid my above described error (STWithin doesn't return a BOOLEAN!!)
-- declaration of parameters for above sql
SET #sql_param_def = '#limit int, #geobb geometry';
EXECUTE sp_executesql #sql_statement, #sql_param_def, #limit = #row_limit, #geobb = #bb;
Hope this was clear ;-)
create proc usp_insert_Proc_Into_temp
#tempTable nvarchar(10) output
as
begin
set #tempTable = '##temp'
declare #query nvarchar(200)
--Select statement
set #query = 'select 1 as A,2 as B, 3 as C into'+ ' '+#tempTable+''
exec(#query)
end
go
declare #tempTable nvarchar(10)
exec usp_insert_Proc_Into_temp #tempTable output
exec('select * from' + ' '+ #tempTable+'')
exec ('drop table'+ ' '+#tempTable+'')