Conversion failed when converting the nvarchar value 'INSERT into dbo - sql

I know this question might be repeated. I have checked my query more than 2 times but I don't know what is the problem?
Here is my stored procedure with cursor:
ALTER PROCEDURE [dbo].[SPApprove_Request](#Id int, #NumRowsChanged int OUTPUT)
AS
BEGIN TRAN ApprovalTransaction
DECLARE #Mapping_Id int, #C_Id int, #Service_Table varchar(50), #Ser_Id int, #sql nvarchar(4000), #Today_Date datetime
SET #Today_Date=GETDATE()
DECLARE cursorObj CURSOR LOCAL static FOR SELECT serType.Service_Table_Name, serMap.Id, serMap.Request_Id FROM [Service_Type] as serType, [Service_Mapping] as serMap WHERE serType.Id = serMap.Service_Type_Id AND serType.Id IN (SELECT Service_Type_Id FROM Service_Mapping WHERE Request_Id = #Id) and serMap.Request_Id=#Id
OPEN cursorObj
--SELECT ##CURSOR_ROWS AS TotalRows
FETCH NEXT FROM cursorObj into #Service_Table, #Mapping_Id, #C_Id
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'INSERT into dbo.' + quotename(#Service_Table) + '(Request_Id, Is_Active, Is_Deleted, Is_Cancelled, Created_Date) VALUES (' + #C_Id + ',1, 0, 0,'''+ convert(VARCHAR,#Today_Date) +''')'
EXEC sp_executesql #sql
SELECT #Ser_Id = ##IDENTITY
IF (##ERROR <> 0) GOTO ERR_HANDLER
UPDATE [Service_Mapping] SET Service_Id = #Ser_Id WHERE Id = #Mapping_Id
FETCH NEXT FROM cursorObj into #Service_Table, #Mapping_Id, #C_Id
END
CLOSE cursorObj
DEALLOCATE cursorObj
UPDATE [Request] SET State_Id = 2, Service_State_Id = 1, Approve_Disapprove_Date = #Today_Date, Date_Modified = #Today_Date WHERE Id = #Id
SELECT #NumRowsChanged = ##ROWCOUNT
COMMIT TRAN ApprovalTransaction
RETURN #NumRowsChanged
ERR_HANDLER:
PRINT 'Unexpected error occurred while Approving CRM Request!'
ROLLBACK TRAN ApprovalTransaction
Getting error:
Msg 245, Level 16, State 1, Procedure SPApprove_CRM_Doctor_Request,
Line 19
Conversion failed when converting the nvarchar value 'INSERT
into dbo.[Financial_Assistance](CRM_Doctor_Request_Id, Is_Active,
Is_Deleted, Is_Cancelled, Created_Date) VALUES (' to data type int.

You should convert #C_Id to varchar in order to concatenate it to a string.
SET #sql = 'INSERT into dbo.' + quotename(#Service_Table) +
'(Request_Id, Is_Active, Is_Deleted, Is_Cancelled, Created_Date)
VALUES (' + convert(varchar,#C_Id) + ',1, 0, 0,'''+ convert(VARCHAR,#Today_Date) +''')'

Also you can use sp_executesql system stored procedure with parameters
SET #sql = 'INSERT into dbo.' + quotename(#Service_Table) + '(Request_Id, Is_Active, Is_Deleted, Is_Cancelled, Created_Date) VALUES (#C_Id,1, 0, 0,#Today_Date)'
EXEC sp_executesql #sql, N'#C_Id int, #Today_Date datetime', #C_Id, #Today_Date

Related

Select into is selecting last record when trying to generate dynamic update statement for each table

I have a table like below :
Archival:
TableName ColumnName Datatype NewValue
Employee FirstName nvarchar Abc
Employee LastName nvarchar Pqr
Employee Age int 28
Address City nvarchar Chicago
Address StreetName nvarchar KKKKK
I am trying to create dynamic update statement for each table and want to execute update statement for each individual table and rollback if any update fails.
Expected update statement query for each individual table:
Update Employee set FirstName = 'Abc', LastName = 'Pqr', Age = 21
where DepartmentId = 100;
Update Address set City = 'Chicago', StreetName = 'KKKKK'
where DepartmentId = 100;
Stored Procedure:
Alter PROC [dbo].[UpdateDataByDeptID]
#departmentId int
As
Begin
Declare db_cursor CURSOR for select TableName from Archival
group by TableName
Declare #tableName nvarchar(50),
#columnName nvarchar(50),
#datatype nvarchar(50),
#newValue nvarchar(50)
open db_cursor
Fetch Next from db_cursor into #tableName;
While ##FETCH_STATUS = 0
Begin
select #columnName = ColumnName,
#datatype = Datatype,
#newValue = NewValue
from Archival where TableName = #tableName;
print #tableName + ' ' + #columnName + ' ' + #newValue
Fetch Next from db_cursor into #tableName
End;
close db_cursor;
DEALLOCATE db_cursor;
Begin Transaction
Begin Try
--execute each of the update statement like below for ex:
Update Employee .....
Update Address .....
Commit transaction
End Try
Begin Catch
Rollback
End Catch
End
End -- end of SP
But the problem is this line :
print #tableName + ' ' + #columnName + ' ' + #newValue
Above line is giving me last record for each table. For example for Employee table :
Employee Age int 28
Hence I am not able to generate individual update statement for each table.
Final expected output is below for my transaction after each update statement for each individual table:
Begin Transaction
Begin Try
--execute each of the update statement like below for ex:
Update Employee set FirstName = 'Abc', LastName = 'Pqr', Age = 21
where DepartmentId = 100;
Update Address set City = 'Chicago', StreetName = 'KKKKK'
where DepartmentId = 100;
Commit transaction
End Try
Begin Catch
Rollback
End Catch
End
Can someone please help me with this?
An example of how you could approach something like this is by using dynamic SQL.
For example:
DECLARE #sql NVARCHAR(MAX) = N'';
DECLARE #tablename NVARCHAR(255);
DECLARE db_cursor CURSOR FOR
SELECT DISTINCT [TableName] FROM [Archival];
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #tablename;
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #sql += N'UPDATE ' + QUOTENAME(#tablename) + ' SET ';
SELECT #sql += QUOTENAME([ColumnName]) + N' = ' + QUOTENAME([NewValue], '''') + N', '
FROM [Archival]
WHERE [TableName] = #tablename;
SELECT #sql = SUBSTRING(#sql, 1, LEN(#sql) - 1) + N'
WHERE DepartmentId = 100;
';
FETCH NEXT FROM db_cursor INTO #tablename;
END
CLOSE db_cursor;
DEALLOCATE db_cursor;
PRINT #sql;
-- EXEC sp_executesql #sql;
Which should give you something to your expected output, I believe.
I would be careful when doing something like this though if you can't trust what's in the NewValue column. (e.g. if it's possible for someone to put in some sort of malicious SQL that would be executed here).

MS SQL query - if not exists a table

I make a cursor (MSSQL):
CREATE TABLE #temp
(
DB VARCHAR(50),
Tab VARCHAR(50),
[COUNT] INT
)
DECLARE #db_name NVARCHAR (150)
DECLARE #tab1 NVARCHAR (150)
set #tab1 = 'dbo.test'
DECLARE c_db_names CURSOR FOR
SELECT name
FROM sys.databases
WHERE name like '%KNF%'
OPEN c_db_names
FETCH c_db_names INTO #db_name
WHILE ##Fetch_Status = 0
BEGIN
EXEC('
INSERT INTO #temp
SELECT ''' + #db_name + ''',''' + #tab1 + ''',COUNT(*) FROM ' + #db_name + '.' + #tab1 + '
')
FETCH c_db_names INTO #db_name
END
CLOSE c_db_names
DEALLOCATE c_db_names
SELECT * FROM #temp
DROP TABLE #temp
The cursor counts the number of rows in each database table. If there is no such table there is an error.
(1 row(s) affected)
(1 row(s) affected)
Msg 208, Level 16, State 1, Line 2
Invalid object name 'KNF_C.dbo.test'.
(2 row(s) affected)
What is obvious, because the KNF_C database does not have this table. I would like the entire cursor to handle such an exception.
The expected result:
DB Tab COUNT
KNF_A dbo.test 3
KNF_B dbo.test 7
KNF_C no table
I know I should use syntax for example if exist but i dont know how.
Please help to solve this
On SQL Server you can check the existence of an object using OBJECT_ID:
IF OBJECT_ID('dbo.table_name') IS NOT NULL
DO SOMETHING;
Or use INFORMATION_SCHEMA.TABLES instead of sys.databases.
What you have to do is dynamically call the sysobjects table to get if the table exists and then conditionally choose what you want to insert into your temp table.
This probably the code you need:
CREATE TABLE #temp
(
DB VARCHAR(50),
Tab VARCHAR(50),
[COUNT] INT
)
DECLARE #str NVARCHAR(1000)
DECLARE #db_name NVARCHAR (150)
DECLARE #tab1 NVARCHAR (150)
DECLARE #count INT
set #tab1 = 'dbo.test'
DECLARE c_db_names CURSOR FOR
SELECT name
FROM sys.databases
WHERE name like '%KNF%'
OPEN c_db_names
FETCH c_db_names INTO #db_name
WHILE ##Fetch_Status = 0
BEGIN
SET #str = N'Select #internalVariable = (select count(1) from ' + #db_name + '.dbo.sysobjects where name = ''' + replace(#tab1, 'dbo.','') + ''') '
exec sp_executesql
#str, --dynamic query
N'#internalVariable int output', --query parameters
#internalVariable = #count output --parameter mapping
IF ( #count = 1 )
BEGIN
EXEC('
INSERT INTO #temp
SELECT ''' + #db_name + ''',''' + #tab1 + ''',COUNT(*) FROM ' + #db_name + '.' + #tab1 + '
')
END
ELSE
BEGIN
EXEC('
INSERT INTO #temp
SELECT ''' + #db_name + ''',''no table'', null
')
end
FETCH c_db_names INTO #db_name
END
CLOSE c_db_names
DEALLOCATE c_db_names
SELECT * FROM #temp
DROP TABLE #temp

The number of variables declared in the INTO list must match that of selected columns one select one into

This is a pretty straightforward error, but I can't figure out why I am getting it. I have one column selected in my declare (TABLE_NAME) and am fetching into one variable (#cTableName). What gives?
CREATE PROCEDURE [dbo].[updateNumbers_ArchiveDB]
(
#accountNumber varchar(50),
#padding varchar(50),
#proc_dateStart datetime,
#proc_dateEnd datetime
)
AS
DECLARE #cTableName varchar(50)
DECLARE CursorYearlyTables CURSOR FOR
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME like 'Archive[12]%' and len(TABLE_NAME) = 14
ORDER BY TABLE_NAME;
-- =============================================
-- Open the cursor and iterate over the monthlies
-- =============================================
OPEN CursorYearlyTables
fetch next from CursorYearlyTables into #cTableName
while (##fetch_status <> -1)
BEGIN
SET NOCOUNT ON;
declare #q varchar(1000);
set #q = 'Update' + #cTableName +
'SET LogicalAccount = #padding + #accountNumber' +
'WHERE ProcessDate BETWEEN CAST(#proc_dateStart AS DATE) AND CAST(#proc_dateEnd AS DATE)'
exec(#q)
fetch next from CursorYearlyTables into #cTableName
END
close CursorYearlyTables;
DEALLOCATE CursorYearlyTables;
Could you try it with these lines in the cursor
declare #q nvarchar(max);
set #q = 'Update ' + #cTableName +
'SET LogicalAccount = '+#padding + #accountNumber +
'WHERE ProcessDate BETWEEN CAST('''+CONVERT(VARCHAR(20),#proc_dateStart)+''' AS DATE) AND CAST('''+CONVERT(VARCHAR(20),#proc_dateEnd)+''' AS DATE)'
exec sp_executesql #q
to account for SQL_Injection DavidG commented:
declare
#q nvarchar(max) = 'update '+#cTableName+' SET LogicalAccount = #a where ProcessDate BETWEEN CAST(#b AS DATE) AND CAST(#c AS DATE))',
#param1 nvarchar(100) = #padding+ #accountNumber,
#ParamDefinition nvarchar(500) = N'#a varchar(100), #b datetime, #c datetime'
exec sp_executesql #q, #ParamDefinition,#a = #param1,#b = #proc_dateStart, #cTableName = #proc_dateEnd
Please use CONVERT function
CAST('''+CONVERT(VARCHAR(108),#proc_dateStart)+''' AS DATE) AND CAST('''+CONVERT(VARCHAR(108),#proc_dateEnd)+''' AS DATE)'

Error coming while creating UDF in Sql Server 2005

Does anyone know what's wrong with this code block.
CREATE FUNCTION [dbo].[udfGetPoint]
(
#UserID INT,
#SqlCountry VARCHAR(1000)
)
RETURNS INT
AS
BEGIN
DECLARE #Points INT
SET #Points = 1
DECLARE #RecordCount sysname
IF #SqlCountry <> ''
BEGIN
EXEC sp_executesql
N'SELECT #DynamicCount = COUNT(UserID) FROM Country WHERE UserID = '+#UserID+' AND LCValues IN (' + #SqlCountry + ')'
,N'#DynamicCount sysname OUTPUT'
,#RecordCount OUTPUT
IF #RecordCount > 0
SET #Points = #Points + 1
END
RETURN #Points
END
If i execute this i got following error:
Msg 102, Level 15, State 1, Procedure udfGetPoint, Line 15
Incorrect syntax near '+'.
You can't concatenate in the parameter setting of a stored procedure.
DECLARE #sql varchar(2000)
SET #SQL = 'SELECT #DynamicCount = COUNT(UserID) FROM Country WHERE UserID = '+#UserID+' AND LCValues IN (' + #SqlCountry + ')'
EXEC sp_executesql
#SQL
,N'#DynamicCount sysname OUTPUT'
,#RecordCount OUTPUT

Creating A Script To Replicate A Table And Its Contents?

I know you can create a script to replicate a table using:
right click table > script table as > create to > new query editor window
But how can I generate a script that contains a bunch of insert commands for each row in the table?
Table1
Id1, Row1
Id2, Row2
Id3, Row3
Insert into Table1 values(Row1);
Insert into Table1 values(Row2);
Insert into Table1 values(Row3);
I ended up doing this
right click database > Tasks > Generate Scripts ... > selected the tables > in the advanced options I set "Types of data to script" to "Schema and data"
Select
'Insert into Table (
IntField1
StringField2
Column3)
values (' +
IntField1 + ',' +
+ '''' + StringField2 + ''',' +
Column2 + ')' as InsertQuery
From Table
Something like this, just remember if your string contains a single quote you will need to make sure you replace it like this replace(stringfield, '''', '''''')
So this isnt super pretty cuz I kind of took one of my sp's and hacked it up for this. But basically this will take any table and print a series of insert statements into a table called tbl_text (which you would need to create)
The arguments are the table name and the table ID from sysobjects
--this is how you get the tbl_id
SELECT id FROM sysobjects WHERE type = 'U' AND name = 'tablename'
CREATE PROCEDURE dbo.sp_export_table
#tblhdr varchar(100),
#tblID varchar(100)
AS
SET NOCOUNT ON
IF object_id('tempdb..##temptable') IS NOT NULL
BEGIN
DROP TABLE ##temptable
END
DECLARE #identity bit
DECLARE #typestmt nvarchar(100)
DECLARE #typeval int
DECLARE #rowstmt nvarchar(1000)
DECLARE #rowID varchar(50)
DECLARE #orderby nvarchar(100)
DECLARE #clmnstmt varchar(200)
DECLARE #clmnhdr varchar(50)
DECLARE #clmnstring varchar(1000)
DECLARE #valuestmt nvarchar(200)
DECLARE #valuestring nvarchar(3000)
DECLARE #value nvarchar(1000)
DECLARE #insertstmt varchar(1000)
DECLARE #params nvarchar(100)
DECLARE #param2 nvarchar(100)
SELECT #rowstmt = N'SELECT TOP 1 #inside_var = name FROM syscolumns WHERE id = ' + #tblID + ' ORDER BY colorder'
SELECT #params = N'#inside_var NVARCHAR(1000) OUTPUT'
EXEC sp_executesql #rowstmt, #params, #inside_var = #orderby OUTPUT
SELECT #rowstmt = 'SELECT *, ROW_NUMBER() OVER (ORDER BY ' + #orderby + ') AS row INTO ##temptable FROM ' + #tblhdr
exec(#rowstmt)
IF object_id('tempdb..##temptable') IS NOT NULL
BEGIN
DECLARE row_cursor CURSOR FOR
SELECT row FROM ##temptable
OPEN row_cursor
FETCH NEXT FROM row_cursor
INTO #rowID
--if table has identity and has records write identity_insert on
SET #identity = 0
IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE OBJECTPROPERTY(OBJECT_ID(TABLE_NAME),
'TableHasIdentity') = 1 AND TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME = #tblhdr) AND EXISTS(SELECT * FROM ##temptable)
BEGIN
SET #identity = 1
INSERT INTO dbo.tbl_text VALUES('SET IDENTITY_INSERT dbo.' + #tblhdr + ' ON')
END
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #clmnstmt = 'DECLARE column_cursor CURSOR FOR SELECT name FROM syscolumns WHERE id = ' + #tblID + ' ORDER BY colorder'
exec(#clmnstmt)
OPEN column_cursor
FETCH NEXT FROM column_cursor
INTO #clmnhdr
SELECT #clmnstring = '('
SELECT #valuestring = '('
WHILE ##FETCH_STATUS = 0
BEGIN
IF #clmnhdr <> 'row'
BEGIN
SELECT #clmnstring = #clmnstring + #clmnhdr + ','
SELECT #valuestmt = N'SELECT #inside_var = ' + #clmnhdr + ' FROM ##temptable WHERE row = ' + #rowID
EXEC sp_executesql #valuestmt, #params, #inside_var = #value OUTPUT
SELECT #typestmt = N'SELECT #inside_var2 = xtype FROM syscolumns WHERE name = ''' + #clmnhdr + ''' AND id = ' + #tblID
SELECT #param2 = N'#inside_var2 INT OUTPUT'
EXEC sp_executesql #typestmt, #param2, #inside_var2 = #typeval OUTPUT
IF #typeval NOT IN (48,52,56,59,60,62,104,108,122,127)
BEGIN
SET #value = REPLACE(#value,'''','''''')
SET #value = '''' + #value + ''''
SET #value = ISNULL(#value, '''''')
END
IF NOT (#typeval = 34)
BEGIN
SELECT #valuestring = #valuestring + #value + ','
END
ELSE
BEGIN
SELECT #valuestring = #valuestring + '''''' + ','
END
END
FETCH NEXT FROM column_cursor
INTO #clmnhdr
END
SET #clmnstring = LEFT(#clmnstring, LEN(#clmnstring) - 1)
SET #valuestring = LEFT(#valuestring, LEN(#valuestring) - 1)
INSERT INTO dbo.tbl_text VALUES('INSERT INTO dbo.' + #tblhdr + ' ' + #clmnstring + ') VALUES' + #valuestring + ')')
FETCH NEXT FROM row_cursor
INTO #rowID
CLOSE column_cursor
DEALLOCATE column_cursor
END
--if it wrote identity_insert on, turn it off
IF (#identity = 1)
BEGIN
INSERT INTO dbo.tbl_text VALUES('SET IDENTITY_INSERT dbo.' + #tblhdr + ' OFF')
END
CLOSE row_cursor
DEALLOCATE row_cursor
END
IF object_id('tempdb..##temptable') IS NOT NULL
BEGIN
DROP TABLE ##temptable
END
GO
If you've got an account on SSC, you can use the script I published last year. It works without cursors an it enables custom filtering.
http://www.sqlservercentral.com/scripts/Script+Data/65998/
Hope this helps
Assuming Row is an INT NOT NULL. You could write a SELECT statement that outputs SQL;
SELECT N'INSERT INTO Table1 VALUES (' + CAST(Row AS NVARCHAR(10)) + N');'
FROM Table1
Then output your results to text.