Error "Incorrect syntax near the keyword 'CONVERT'" - sql-server

I have the below T SQL statement but keep getting the error
Incorrect syntax near the keyword 'CONVERT'
Where am I going wrong?
DECLARE #NSQL2 NVARCHAR(MAX)
DECLARE #SOURCETABLE NVARCHAR(MAX)
SELECT TOP 1 #SOURCETABLE = TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'IN_PRODUCT________________%'
AND TABLE_TYPE = 'BASE TABLE'
SET #NSQL2 = 'UPDATE [' + #SOURCETABLE + '] SET OnSale = '''+ CONVERT(nvarchar(MAX),OnSale, 112)+'''
EXEC SP_EXECUTESQL #NSQL2

Try this:
SET #NSQL2 = 'UPDATE ' + QUOTENAME(#SOURCETABLE)
+ ' SET OnSale = CONVERT(nvarchar(10),OnSale, 112)'

I got it to work using the below:
SET #NSQL = 'UPDATE [' + #SOURCETABLE + '] SET OnSale = CONVERT(nvarchar,CAST(OnSale AS DATETIME), 120)'

Did you intend for the Convert statement to be part of your string as a literal?
SET #NSQL2 = 'UPDATE [' + #SOURCETABLE + '] SET OnSale = CONVERT(nvarchar(MAX),OnSale, 112)'

Related

SQL Syntax Error in print functions using dynamic variables

When I run the below query, It does print the statements but throws the following error:
Process failed: Incorrect syntax near ')'
Code:
IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'Table_1')
DELETE [dbo].[Table_1]
WHERE [UPDATED_DATE] <= DATEADD(dd, -90,'2018.02.23')
UPDATE DBO.T_REF_MASTER
SET LAST_PURGE_DATE = GETDATE()
WHERE TABLE_NAME = 'Table_1'
Can someone explain why is it throwing that error because when I run the individual statements one by one, it executes perfectly
--Query
DECLARE #SQL VARCHAR(MAX)
DECLARE #S VARCHAR(MAX)
DECLARE #SQLExist VARCHAR(MAX)
DECLARE #db VARCHAR(10) = 'dbo'
DECLARE #TABLE_NAME VARCHAR(200) = 'Table_1'
DECLARE #NO_OF_DAYS VARCHAR(10) = '90'
DECLARE #LAST_PURGE_DATE VARCHAR(50) = '2018-02-22 10:46:49.953'
SET #SQLExist = 'IF EXISTS((SELECT 1 FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '''
+ #db + ''' AND TABLE_NAME = ''' + #TABLE_NAME +
''')'
--PRINT #SQLExist
SET #SQL = 'DELETE [' + #db + '].[' + #TABLE_NAME
+ '] where [UPDATED_DATE] <= DATEADD(dd, -'
+ CONVERT(VARCHAR,#NO_OF_DAYS) + ',''' +
+ CONVERT(VARCHAR,#LAST_PURGE_DATE, 102) + ''')'
--PRINT #SQL
SET #S = 'UPDATE DBO.T_REF_MASTER SET LAST_PURGE_DATE =
getdate() WHERE TABLE_NAME = '
+ '''' + CONVERT(VARCHAR, #TABLE_NAME) + ''');'
PRINT #SQLExist
print #SQL
PRINT #S
I see two opening parentheses - (( - after EXISTS, but only one closing after #TABLE_NAME.
Okay agreed George. I removed those parentheses. Here's the new query:
--Query
DECLARE #SQL VARCHAR(MAX)
DECLARE #S VARCHAR(MAX)
DECLARE #SQLExist VARCHAR(MAX)
DECLARE #db VARCHAR(10) = 'dbo'
DECLARE #TABLE_NAME VARCHAR(200) = 'Table_1'
DECLARE #NO_OF_DAYS VARCHAR(10) = '90'
DECLARE #LAST_PURGE_DATE VARCHAR(50) = '2018-02-22 10:46:49.953'
SET #SQLExist = 'IF EXISTS(SELECT 1 FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '''
+ #db + ''' AND TABLE_NAME = ''' + #TABLE_NAME +
''')'
--PRINT #SQLExist
SET #SQL = 'DELETE [' + #db + '].[' + #TABLE_NAME
+ '] where [UPDATED_DATE] <= DATEADD(dd, -'
+ CONVERT(VARCHAR,#NO_OF_DAYS) + ',''' +
+ CONVERT(VARCHAR,#LAST_PURGE_DATE, 102) + ''')'
--PRINT #SQL
SET #S = 'UPDATE DBO.T_REF_MASTER SET LAST_PURGE_DATE =
getdate() WHERE TABLE_NAME = '
+ '''' + CONVERT(VARCHAR, #TABLE_NAME) + ''''
PRINT #SQLExist
print #SQL
PRINT #S
Its still spitting out the SYNTAX ERROR NEAR ')'

Trouble using EXEC Command in SQL Server

Apparently there is a syntax error when i try to use the exec command to call parameter var's for table names.
Here's my code:
ALTER PROCEDURE [dbo].[createTable]
#tblName varchar(30),
#tblSTDColumns int = 0,
#dupExistTblName varchar(60) = ''
AS
BEGIN
SET NOCOUNT ON;
SET #dupExistTblName = #tblName + '_COPY'
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES
WHERE table_name LIKE #tblName)
(
EXEC('SELECT * INTO [' + #dupExistTblName + '] FROM [' + #tblName + '] WHERE 1=2')
)
EXEC('DROP TABLE ['+ #tblName + ']')
EXEC('SELECT * INTO [' + #tblName + '] FROM [' + #dupExistTblName] + ' WHERE 1=2')
END
The line EXEC('SELECT * INTO [' + #dupExistTblName + '] FROM [' + #tblName + '] WHERE 1=2') generates a syntax error
You were missing some things, and misplacing others.
CREATE PROCEDURE [dbo].[createTable]
#tblName varchar(30),
#tblSTDColumns int = 0,
#dupExistTblName varchar(60) = ''
AS
BEGIN
SET NOCOUNT ON;
SET #dupExistTblName = #tblName+'_COPY'
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES where table_name like #tblName)
BEGIN
EXEC('SELECT * INTO [' + #dupExistTblName + '] FROM [' + #tblName + '] WHERE 1=2')
END
ELSE
BEGIN
EXEC('DROP TABLE ['+ #tblName + ']')
EXEC('SELECT * INTO [' + #tblName + '] FROM [' + #dupExistTblName + '] WHERE 1=2')
END
END
A) MSDN states this on every relevant page:
Validate all user input. Do not concatenate user input before you
validate it. Never execute a command constructed from unvalidated user
input.
B) IF statements in TSQL only work on the next proceeding query/command line in SQL. Using BEGIN END is a good way of ensuring proper execution. Your style of course, but being explicit is preferred.
C) Declaring variables between CREATE/ALTER and AS BEGIN imply you want those variables to have user input. (#dupExistTblName) is immediately replaced?
Below is one method that includes a style of security with the added bonus of RAISERROR to prevent fatal errors and provide feedback.
ALTER PROCEDURE [dbo].[createTable]
#tblName varchar(30)
-- #tblSTDColumns int = 0
AS
BEGIN
SET NOCOUNT ON;
DECLARE #string NVARCHAR(255);
IF OBJECT_ID(#tblName) IS NOT NULL
BEGIN
DECLARE #dupExistTblName varchar(60);
SET #dupExistTblName = #tblName + '_COPY';
BEGIN
SET #string = N'SELECT * INTO ' + QUOTENAME(#dupExistTblName) + ' FROM ' + QUOTENAME(#tblName) + ' WHERE 1=2';
--SELECT #string
EXEC (#string);
END
END
ELSE
-- no need for a fatal error from trying to input a bad table name.
RAISERROR('Unknown Error. You Entered: %s. Check syntax.'
, 10
, 1
, #tblName)
END
EXEC dbo.createTable #tblName = 'MyNAMEST'
Unknown Error. You Entered: MyNAMEST. Check syntax.
To add further protections, MSDN promotes use of sp_executesql which allows for caching of SQL statement themselves. There many different ways to write, such as the following:
EXEC sp_executesql N'SELECT * INTO QUOTENAME(#TblcopyName)
FROM QUOTENAME(#tbleName) WHERE 1 = 2'
, N'#TblcopyName NVARCHAR(50), #tbleName NVARCHAR(50)'
, #TblcopyName = #dupExistTblName
, #tblName = #tblName
Here's what I ended up with! Thanks everyone!
ALTER PROCEDURE [dbo].[createTable]
-- Add the parameters for the stored procedure here
#tblName varchar(30),
#dupExistTblName varchar(60) = ''
AS
BEGIN
SET NOCOUNT ON;
SET #dupExistTblName = #tblName+'_COPY'
PRINT #tblName + '-tbl name ' + #dupExistTblName
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES where table_name like #tblName)
BEGIN
BEGIN TRY
EXEC('SELECT * INTO [' + #dupExistTblName + '] FROM [' + #tblName + '] WHERE 1=2')
END TRY
BEGIN CATCH
END CATCH
EXEC('DROP TABLE ['+ #tblName + ']')
PRINT 'TABLE DROPPED'
EXEC('SELECT * INTO [' + #tblName + '] FROM [' + #dupExistTblName + '] WHERE 1=2')
END
END

The multi-part identifier could not be bound in Dynamic SQL using Trigger

Following is a part of my instead of update trigger
CREATE TRIGGER TestDemo ON Consultants1
INSTEAD OF UPDATE
AS
DECLARE #Sql nvarchar(200),
#TableName nvarchar(50),
#FieldName nvarchar(100),
#PKCols VARCHAR(1000), --Primary Key
#Value nvarchar(100)
SET #TableName = 'Consultants1'
SET #FieldName = 'DisplayName'
SET #Value = 'Test123'
SELECT * INTO #ins FROM inserted
SELECT #PKCols = c.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,
INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
WHERE pk.TABLE_NAME = #TableName
AND CONSTRAINT_TYPE = 'PRIMARY KEY'
AND c.TABLE_NAME = pk.TABLE_NAME
AND c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME
SELECT #Sql = 'UPDATE ' + #TableName + ' SET '
SELECT #Sql = #Sql + #FieldName + ' = ''' + #Value + ''''
SELECT #Sql = #Sql + ' WHERE #ins.' + #PKCols + ' = ' + #TableName + '.' + #PKCols
EXEC (#Sql)
The trigger gets created without any errors.
Now I am trying to execute the following query
UPDATE Consultants1 SET DisplayName = 'abcd'
where ConsIntID = 'Test123285'
It gives a error saying:
Msg 4104, Level 16, State 1, Line 1
The multi-part identifier "#ins.ConsIntID" could not be bound.
I could not understand where my code goes wrong. Please help
You may change this line of code
SELECT #Sql = #Sql + ' WHERE #ins.' + #PKCols + ' = ' + #TableName + '.' + #PKCols
to this
SELECT #Sql = #Sql + ' FROM #ins a INNER JOIN ' + #TableName + ' b ON a.' + #PKCols + ' = b.' + #PKCols
Another story is that after the change you'll probably receive an error: Msg 570, Level 16, State 1, Line 1
INSTEAD OF triggers do not support direct recursion. The trigger execution failed.
Here's a good article about INSTEAD OF triggers and recursion in MSDN. Check the Remarks section.

Convert blank to NULL for a table

In my table I have few columns which are having blank values. Can anyone suggest me a query by which I can replace all blanks to NULL for a given table?
EDIT
I am sorry if I couldn't specify my question correctly, I don't want to give the column name in my query. All I have is the table name. So, for a given table I want to check all columns and convert their blank values to NULL.
As an approach next stored procedure could be help:
CREATE PROCEDURE up_replaceBlanksByNulls
#schemaName nvarchar(50),
#tableName nvarchar(100)
AS
declare #query1 nvarchar(max) = ''
select #query1 = #query1 + 'UPDATE ' + #schemaName + '.' + #tableName + ' SET ' + c.COLUMN_NAME + ' = NULL WHERE ' +
c.COLUMN_NAME + ' = '''';' FROM INFORMATION_SCHEMA.COLUMNS c
WHERE C.TABLE_NAME = #tableName
EXECUTE sp_executesql #query1
GO
Usage:
up_replaceBlanksByNulls 'dbo', 'myTable'
To get rid of all blank values in a table :
CREATE PROCEDURE getRidOfBlanks
#tableName nvarchar(50)
AS
DECLARE #colName varchar(50)
DECLARE Table_Cursor CURSOR FOR
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME='#tableName'
OPEN Table_Cursor;
FETCH NEXT FROM Table_Cursor INTO #colName
WHILE ##FETCH_STATUS = 0
BEGIN
UPDATE #tableName SET #colName = NULL WHERE #colName = '';
FETCH NEXT FROM Table_Cursor INTO #colName
END;
CLOSE Table_Cursor;
DEALLOCATE Table_Cursor;
GO
To use this, you create your procedure with my code, then you execute it with your tableName.
Simply using UPDATE like this:
UPDATE myTable SET myColumn = NULL WHERE myColumn = '';
If your column names have spaces in them, here is an alteration of #alex.b procedure.
CREATE PROCEDURE up_replaceBlanksByNulls
#schemaName nvarchar(50),
#tableName nvarchar(100)
AS
declare #query1 nvarchar(max) = ''
select #query1 = #query1 + 'UPDATE ' + #schemaName + '.' + #tableName + ' SET ' + case when c.COLUMN_NAME like '% %' then '[' + c.COLUMN_NAME + ']' Else c.COLUMN_NAME end + ' = NULL WHERE ' +
case when c.COLUMN_NAME like '% %' then '[' + c.COLUMN_NAME + ']' Else c.COLUMN_NAME end + ' = '''';' FROM INFORMATION_SCHEMA.COLUMNS c
WHERE C.TABLE_NAME = #tableName
print #query1
EXECUTE sp_executesql #query1
GO

SQLServer conditional execution within 'EXEC' if a column exists

I'm new to SQLServer scripting (normally being a C++ developer), and would really appreciate a bit of assistance.
I am attempting to perform a "find and replace" update on all tables in a SQLServer database that contain a 'PROJID' column. I am really struggling to find a way to do this that doesn't report to me:
Msg 207, Level 16, State 1, Line 1 Invalid column name 'PROJID'.
The statement I am executing is:
EXEC
(
'IF EXISTS(SELECT * FROM sys.columns WHERE name = N''PROJID'' AND Object_ID = Object_ID(N''' + #TableName + '''))' +
' BEGIN' +
' UPDATE ' + #TableName +
' SET ' + #ColumnName + ' = REPLACE(' + #ColumnName + ',''' + #ReplaceIDStr + ''',''' + #FindIDStr + ''')' +
' WHERE ' + #ColumnName + ' LIKE ''' + #ReplaceIDStr + '''' + ' AND PROJID = ''1000''' +
' END'
)
I have also tried using:
'IF COL_LENGTH(''' + #TableName + ''',''PROJID'') IS NOT NULL' +
instead of the column-exist check above. This also still gives me the "Invalid Column Name" messages.
I would be happy to take the column-exist check outside of the 'Exec' statement, but I'm not sure how to go about doing this either.
You just need to do it in a different scope.
IF EXISTS (SELECT 1 FROM sys.columns ...)
BEGIN
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'UPDATE ...';
EXEC sp_executesql #sql;
END
Output the results of this query to text. Don't forget to change the values of the variables! Take the result of this and run it.
SET NOCOUNT ON
DECLARE #ColumnName VARCHAR(200) = 'ReplaceColumn'
, #ReplaceIdStr VARCHAR(200) = 'ExampleReplaceIdStr'
, #FindIdStr VARCHAR(200) = 'ExampleFindIdStr'
PRINT 'BEGIN TRAN'
PRINT 'SET XACT_ABORT ON'
SELECT
'UPDATE ' + C.TABLE_NAME + CHAR(13)
+ 'SET ' + #ColumnName + ' = REPLACE(' + #ColumnName + ', ''' + #ReplaceIdStr + ''', ''' + #FindIdStr + ''')' + CHAR(13)
+ 'WHERE ' + #ColumnName + ' LIKE ''%' + #ReplaceIdStr + '%'' AND PROJID = ''1000''' + CHAR(13)
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.COLUMN_NAME = 'PROJID'
PRINT 'COMMIT TRAN'
SET NOCOUNT OFF
EDIT: Also, some reasoning: You said you want update all tables where they contain a column called PROJID. Your first query just says that if the table #TableName has a PROJID column, then update #ColumnName on it. But it doesn't guarantee that it has #ColumnName on it. The query I gave doesn't check that either, because I'm assuming that all tables that have PROJID also have #ColumnName. If that isn't the case, let me know and I can update the answer to check that. That you're getting an Invalid Column Name error points to #ColumnName not existing.
Your query would have updated one table (#TableName) at most, whereas the one I gave you will update every table that has PROJID. I hope that's what your going for.
EDIT 2: Here is a version that would run it all at once:
DECLARE #ColumnName VARCHAR(200) = 'Value'
, #ReplaceIdStr VARCHAR(200) = 'ExampleReplaceIdStr'
, #FindIdStr VARCHAR(200) = 'ExampleFindIdStr'
DECLARE #Sql NVARCHAR(MAX)
DECLARE UpdateCursor CURSOR FOR
SELECT
'UPDATE ' + C.TABLE_NAME
+ ' SET ' + #ColumnName + ' = REPLACE(' + #ColumnName + ', ''' + #ReplaceIdStr + ''', ''' + #FindIdStr + ''')'
+ ' WHERE ' + #ColumnName + ' LIKE ''%' + #ReplaceIdStr + '%'' AND PROJID = ''1000'''
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.COLUMN_NAME = 'PROJID'
OPEN UpdateCursor
FETCH NEXT FROM UpdateCursor
INTO #Sql
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC sp_executesql #Sql
FETCH NEXT FROM UpdateCursor
INTO #Sql
END
CLOSE UpdateCursor
DEALLOCATE UpdateCursor

Resources