Am unable to insert record when given all the column names in insert
Below is the SP
ALTER PROCEDURE [dbo].[test]
#tab_name nvarchar(50),
#tab_id int,
#tab_n nvarchar(50),
#tab_q int
as
Begin
declare #sql as nvarchar(50);
declare #counts as int;
select #sql='select #cnt=count(*) from '+#tab_name+' where id='+cast(#tab_id as varchar)+';'
exec sp_executesql #sql,N'#cnt int output', #cnt=#counts output
select #counts as counts
if #counts=1
begin
declare #sql1 as nvarchar(50);
select #sql1='update '+#tab_name+' set quantity='+cast(#tab_q as varchar)+' where id='+cast(#tab_id as varchar)+';'
exec sp_executesql #sql1
end
else
begin
declare #sql2 as nvarchar(50);
set #sql2='insert into '+#tab_name+' (id,name,quantity) values ('+CAST(#tab_id as varchar)+','''+#tab_n+''''
set #sql2+=','+CAST(#tab_q as varchar)+');'
select #sql2
exec sp_executesql #sql2
end
End
"
command: exec dbo.test #tab_name='inventory',#tab_id=4,#tab_n='chiku',#tab_q=123
record gets inserted when column names are removed but does not work with column names during insert.
Please help.
Thanks
It is better to use A nvarchar(max) for dynamic queries with parameters.
Because u never know how long the string can be. unless you know the max lenght of the string.
A dba also told me to use N' as prefix before the string to denote Unicode string literals.
Increase #sql variables size like below:
declare #sql as nvarchar(max);
....
declare #sql1 as nvarchar(max);
...
declare #sql2 as nvarchar(max);
I have a stored procedure that I'm working on and I'm trying to get it to return the results that are stored into a table variable that I created within the procedure. For some reason, its not returning anything when I execute the procedure. However, if I take the piece of code used to populate the table variable and take it out of the procedure it works...
The code is as follows:
Test Code
DECLARE #RC int
DECLARE #constraint_names nvarchar(max)
DECLARE #column_names nvarchar(max)
DECLARE #table_name nvarchar(max)
DECLARE #table_schema nvarchar(max)
DECLARE #database_name nvarchar(max)
DECLARE #debug int
DECLARE #ExistFlag int;
-- TODO: Set parameter values here.
SET #column_names = 'M2016_Object_ID int, Name varchar(50), a int, b'
SET #table_name = 'tblM2016_Objects';
SET #debug = 0;
SET #ExistFlag = 1;
DECLARE #existing_cols TABLE (Value nvarchar(max));
INSERT INTO #existing_cols EXEC spM2016_CheckColumnExistence_tblM2016
#column_names, #table_name, #database_name, #table_schema, 1, 0;
select * from #existing_cols
Results
Value
M2016_Object_ID int
Name varchar(50)
This is the expected result since I'm testing to see if M2016_Object_ID and Name column exist in the tblM2016_Objects table.
However, when I execute this inside the stored procedure I'm working on, it returns nothing.
Stored Procedure
ALTER PROCEDURE spM2016_ChangePKConstraints_tblM2016
-- Add the parameters for the stored procedure here
#constraint_names nvarchar(max) =
N'PK_tblM2016_Fields_M2016_Field_ID',
#column_names nvarchar(max) = N'M2016_Field_ID',
#table_name nvarchar(max) = N'tblM2016_Fields',
#table_schema nvarchar(max) = N'dbo',
#database_name nvarchar(max) = N'MET',
#debug int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #tbl_name nvarchar(max) = N'tblM2016_Fields',
#col_names nvarchar(max) = N'M2016_Field_ID',
#tbl_schema nvarchar(max) = N'dbo',
#db_name nvarchar(max) = N'MET',
#tbl_full_name nvarchar(max),
#tbl_short_name nvarchar(max),
#sql nvarchar(max),
#params nvarchar(max)
-- Insert statements for procedure here
SET #col_names = ISNULL(NULLIF(#column_names, ''), #col_names);
SET #tbl_name = quotename(ISNULL(NULLIF(#table_name, ''), #tbl_name));
SET #tbl_schema = quotename(ISNULL(NULLIF(#table_schema, ''), #tbl_schema));
SET #db_name = quotename(ISNULL(NULLIF(#database_name, ''), #db_name));
SET #tbl_full_name = #db_name + '.' + #tbl_schema + '.' + #tbl_name;
SET #tbl_short_name = #tbl_schema + '.' + #tbl_name;
DECLARE #existing_cols TABLE (Value nvarchar(max));
DECLARE #nonexisting_cols TABLE (Value nvarchar(max));
--INSERT INTO #split_columns
-- SELECT *
-- FROM
-- fnM2016_Split_String_Inline(#col_names, ',');
--IF (#debug = 1)
-- SELECT * FROM #split_columns;
IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'PK' AND parent_object_id = OBJECT_ID(#tbl_full_name))
BEGIN
-- No PK constraint, check col_names to see which exist and don't exist
INSERT INTO #existing_cols EXEC spM2016_CheckColumnExistence_tblM2016 #col_names, #tbl_name, #db_name, #tbl_schema, 1, 0;
INSERT INTO #nonexisting_cols EXEC spM2016_CheckColumnExistence_tblM2016 #col_names, #tbl_name, #db_name, #tbl_schema, 0, 0;
SELECT * FROM #existing_cols;
SELECT * FROM #nonexisting_cols;
END
--ELSE
--BEGIN
--END
END
Results
These are the results after executing the procedure with the same parameter values in the test above:
EXECUTE #RC = [dbo].[spM2016_ChangePKConstraints_tblM2016]
#constraint_names
,#column_names
,#table_name
,#table_schema
,#database_name
,#debug;
Result
Value
The table purposely does not have a primary key. Proof:
In your procedure, change the name of the table in your Declare section.
This should fix the issue.
ALTER PROCEDURE spM2016_ChangePKConstraints_tblM2016
-- Add the parameters for the stored procedure here
#constraint_names nvarchar(max) =
N'PK_tblM2016_Fields_M2016_Field_ID',
#column_names nvarchar(max) = N'M2016_Field_ID',
#table_name nvarchar(max) = N'tblM2016_Objects',
#table_schema nvarchar(max) = N'dbo',
#database_name nvarchar(max) = N'MET',
#debug int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #tbl_name nvarchar(max) = N'tblM2016_Objects',
#col_names nvarchar(max) = N'M2016_Field_ID',
#tbl_schema nvarchar(max) = N'dbo',
#db_name nvarchar(max) = N'MET',
#tbl_full_name nvarchar(max),
#tbl_short_name nvarchar(max),
#sql nvarchar(max),
#params nvarchar(max)
I figured out the issue. My #table_name, #table_schema, and #database_name being passed into the spM2016_CheckColumnExistence_tblM2016 procedure inside the spM2016_ChangePKConstraints_tblM2016 were already escaped through the call to quotename(). Inside the spM2016_CheckColumnExistence_tblM2016, I also do a qutoename() of the parameters as a validation check against bad table, database, and schema names. That procedure code was left out and I apologize for that.
Essentially the problem area is here (with problem parameters highlighted with **)
Problem code in spM2016_ChangePKConstraints_tblM2016
INSERT INTO #existing_cols EXEC spM2016_CheckColumnExistence_tblM2016 #col_names, **#tbl_name**, **#db_name**, **#tbl_schema**, 1, 0;
Notice that those parameters being passed to spM2016_CheckColumnExistence_tblM2016 have already been escaped with quotename() above in the spM2016_ChangePKConstraints_tblM2016 procedure. Now, here is the missing key code in the spM2016_CheckColumnExistence_tblM2016 procedure:
Problem code in spM2016_CheckColumnExistence_tblM2016
ALTER PROCEDURE spM2016_CheckColumnExistence_tblM2016
-- Add the parameters for the stored procedure here
#column_names nvarchar(max) = N'M2016_Field_ID int',
#table_name nvarchar(max) = N'tblM2016_Fields',
#database_name nvarchar(max) = N'MET',
#table_schema nvarchar(max) = N'dbo',
#ExistFlag int = 1, -- Check for column existence in given table = 1
-- Check for column non-existence in given table = 0
#debug int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #tbl_name nvarchar(max) = N'tblM2016_Fields',
#col_names nvarchar(max) = N'M2016_Field_ID',
#tbl_schema nvarchar(max) = N'dbo',
#db_name nvarchar(max) = N'MET',
#tbl_full_name nvarchar(max),
#tbl_short_name nvarchar(max)
-- Insert statements for procedure here
***** PROBLEM STARTS HERE *****
SET #col_names = ISNULL(NULLIF(#column_names, ''), #col_names);
SET #tbl_name = quotename(ISNULL(NULLIF(#table_name, ''), #tbl_name));
SET #tbl_schema = quotename(ISNULL(NULLIF(#table_schema, ''), #tbl_schema));
SET #db_name = quotename(ISNULL(NULLIF(#database_name, ''), #db_name));
SET #tbl_full_name = #db_name + '.' + #tbl_schema + '.' + #tbl_name;
SET #tbl_short_name = #tbl_schema + '.' + #tbl_name;
I've highlighted the issue with ***** PROBLEM STARTS HERE ***** for clarity. As you can see, spM2016_CheckColumnExistence_tblM2016 also does a quotename call to make sure the #table_name, #table_schema, and #database_name passed to spM2016_CheckColumnExistence_tblM2016 has proper escaping as well. But, since I passed the already quotenamed #table_name, #table_schema, and #database_name from spM2016_ChangePKConstraints_tblM2016 into spM2016_CheckColumnExistence_tblM2016 as #col_names, #tbl_name, #db_name, #tbl_schema, they got double quoted and were thus unrecognizable when doing comparisons in the sys.object queries in spM2016_CheckColumnExistence_tblM2016 and so were returning bogus results.
The reason the test code worked is because the parameters were not already escaped when passed into the spM2016_CheckColumnExistence_tblM2016, thus causing the table variable to execute fine.
Turns out, it had nothing to do with the table variable :/
I am trying to insert a few values into a table using EXECUTE statement.
I have found few examples, however, those does not answer my question.
Note: sources given below are code from the procedure. All mentioned variables was declared and initialized.
First way I tried:
results in:
Error: Procedure or function has too many arguments specified.
And I completely understand why I am getting this. Because sp_executesql does not allow to have more than 4 arguments, and it cannot recognise which goes where.
Second try (where I only want to get the output using execute statement into the variable, and then put that into the table):
And I get:
Must declare scalar variable "#crlf"
and actually this variable is declared in the top of this procedure, but this one is not that clear for me, why it still complains...
What would be the most sufficient way to get the execution statement and the number(additional value) into the table?
As an only workaround I can suggest using a temporary table. Should be quite simple:
SELECT TOP (0) column1
INTO #TemporaryResults
FROM [master].[dbo].[table_1];
INSERT INTO #TemporaryResults
EXECUTE sp_executesql #sql, N'#object_id INT, #crlf CHAR(2)', #object_id, #crlf;
INSERT INTO [master].[dbo].[table_1] (column1, column2)
SELECT column1, 1
FROM #TemporaryResults;
Create a copy of column1 from [table_1] column1
Insert records, produced by SP into it
Insert records to actual table
Please try according with following example
DECLARE #IntVariable int;
DECLARE #SQLString nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
DECLARE #max_title varchar(30);
SET #IntVariable = 197;
SET #SQLString = N'SELECT #max_titleOUT = max(JobTitle)
FROM AdventureWorks2012.HumanResources.Employee
WHERE BusinessEntityID = #level';
SET #ParmDefinition = N'#level tinyint, #max_titleOUT varchar(30) OUTPUT';
EXECUTE sp_executesql #SQLString, #ParmDefinition, #level = #IntVariable, #max_titleOUT=#max_title OUTPUT;
SELECT #max_title;
OBSERVATION
SQL query needs a parameter #level that is why we have declare it as parameter
again the SQL query returns the output at #max_titleOUT. So we also have declare it as parameter. so the final parameter list is
SET #ParmDefinition = N'#level tinyint, #max_titleOUT varchar(30) OUTPUT';
now we have to send the #level value to dynamic query that's why we use #level = #IntVariable that sends the #IntVariable value to #level
Finally by #max_titleOUT = #max_title OUTPUT we take the output of dynamic query that saves at #max_titleOUT, copy the value to #max_title
I was wondering if syntax exist to express something like the following:
DECLARE #MyTableNameVARCHAR(50)
SET #MyTableName= 'AccountSummary'
CREATE TABLE dbo.#MyTableName
(
Id int NOT NULL IDENTITY(1,1),
AccountId int NOT NULL
Amount real
)
Obviously, the above is not working. I made my scripts working with EXEC, but it seems rather convoluted. Can I use CREATE TABLE with a parameter for the tablename?
DECLARE #MyTableName NVARCHAR(50);
SET #MyTableName = 'AccountSummary';
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N'CREATE TABLE '+ QUOTENAME(#MyTableName) + N'
(
Id int NOT NULL IDENTITY(1,1),
AccountId int NOT NULL,
Amount REAL
)'
EXECUTE sp_executesql #Sql
OR
DECLARE #MyTableName NVARCHAR(50);
SET #MyTableName = 'AccountSummary';
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N'CREATE TABLE [#MyTableName]
(
Id int NOT NULL IDENTITY(1,1),
AccountId int NOT NULL,
Amount real
)'
EXECUTE sp_executesql #Sql
,N'#MyTableName NVARCHAR(50)'
,#MyTableName
"Can I use CREATE TABLE with a parameter for the tablename?"
No. You have to use dynamic SQL as you indicate you already have working.
This sort of thing is convoluted by nature.
Depending on what you are actually doing you might feel better about having a app layer constrcut the DDL, rather than doing it all in TSQL.
I'm trying to verify a job number exists on a linked server and get back a variable (#JobExists) indicating whether it does or not (1 for yes, 0 for no).
To do this I'm trying to use OPENQUERY along with sp_executesql as I have to pass in a parameter for the job number. I've tried the code below but get the error 'Procedure expects parameter '#statement' of type 'ntext/nchar/nvarchar'. For testing purposes I've declared and set the variable #JobNumber.
DECLARE #JobNumber as varchar(50)
SET #JobNumber = '2112111'
DECLARE #JobExists as BIT
DECLARE #JobCount as int
DECLARE #ParmDefinition as varchar(100)
DECLARE #sql as varchar(500)
SET #JobExists = 0
SET #ParmDefinition = N'#Result int output'
SET #sql = 'SELECT #Result = SELECT COUNT(*) FROM OPENQUERY(MYLINKEDSVR,''SELECT JOB_NUMBER FROM PROD.tbl1 WHERE JOB_NUMBER = ''''' + UPPER(RTRIM(LTRIM(#JobNumber))) + ''''''')'
exec sp_executesql #sql, #ParmDefinition, #Result = #JobCount output
IF #JobCount > 0
SET #JobExists = 1
SELECT #JobExists
I've read up sp_executesql here: http://technet.microsoft.com/en-us/library/ms188001.aspx
I've also done various searches but haven't come across any answers that work for me.
Is there something I'm missing?
The error message is clear: you must declare #sql as nvarchar and not as varchar.
The same for #ParamDefinition:
DECLARE #ParmDefinition as nvarchar(100)
DECLARE #sql as nvarchar(500)