SQL Server Procedure or function CreateTable has too many arguments specified - sql

I want to create a table with 2 columns: Name of the customer of type varchar and age of type int.
My code:
CREATE PROCEDURE CreateTable
(#tablename varchar(50),
#column varchar(50),
#type varchar(50),
#column2 varchar(20),
#type2 int,
#extra varchar(20) = NULL)
AS
BEGIN
DECLARE #sqlQuery AS varchar(MAX)
SET #sqlQuery = 'CREATE TABLE ' + #tablename + '( id int '+ #column +' ' + #type + #column2 +' ' + #type2+' PRIMARY KEY(id))'
PRINT (#sqlQuery)
EXEC (#sqlQuery)
END
GO
EXEC CreateTable 'Customers', 'Name', 'varchar(50)', 'Age', 'int'
The error is:
Procedure or function CreateTable has too many arguments specified
I don't know where my error is. Please help me.

Should be OK now:
CREATE PROCEDURE CreateTable (
#tablename VARCHAR(50)
,#column VARCHAR(50)
,#type VARCHAR(50)
,#column2 VARCHAR(20)
,#type2 VARCHAR(50)
,#extra VARCHAR(20) = NULL
)
AS
BEGIN
DECLARE #sqlQuery AS VARCHAR(MAX)
SET #sqlQuery = 'create table ' + #tablename + '( id int ,' + #column + ' ' + #type + ' , ' + #column2 + ' ' + #type2 + ' PRIMARY KEY(id))'
PRINT (#sqlQuery)
EXEC (#sqlQuery)
END
GO
EXEC CreateTable 'Customers'
,'Name'
,'varchar(50)'
,'Age'
,'int'
If you compare the parameters you will find the type of #type2 was specified as int while it should be varchar to be part of the executed statement.
You were also missing comma(,) in your executable string inside the stored procedure.

Related

SQL Pass a string to a Stored Procedure that is not a Column Name

Can I pass a String to a Stored Procedure that is not a Column Name?
I need to call the StoredProcedure from C#.
The following does not work as the parameter can't be defined without it's Type, but shows what I am trying to do. Problem is that Sql is looking at #stringToIdentifyDataTable as a ColumnName, which seems fair, but not what I am trying to do.
Alter PROCEDURE [dbo].[PutNewTypeSource] #stringToIdentifyDataTable,
#ID int, #Description varchar(50), #Active bit
AS
DECLARE
#Query AS VARCHAR(MAX),
#Field_Out AS VARCHAR(MAX)
SELECT #Field_Out = CASE #stringToIdentifyDataTable
WHEN 'ReferralSource' THEN '[Adm].[JobReferralSource]'
WHEN 'ReferralSource2' THEN '[Adm].[JobReferralSource2]'
END
SET #Query = concat('
IF EXISTS (SELECT ID FROM ',#Field_Out,' WHERE Description= ',#Description,')
BEGIN
UPDATE ',#Field_Out,
'SET Active = ',#Active,
'WHERE Description= ',#Description,';
END')
EXEC (#Query)
exec [PutNewTypeSource] 'ReferralSource', 1, 'Description1', 0
If I understand correctly what you could do is this. note that I properly quote your object, and importantly parametrise you parameters. What you have before was wide open to injection:
ALTER PROCEDURE [dbo].[PutNewTypeSource] #Referral varchar(50), #Description varchar(50), #Active bit --I remvoed #ID as it was never used
AS BEGIN
DECLARE #Schema sysname,
#Table sysname;
SET #Schema = CASE WHEN #Referral IN ('ReferralSource','ReferralSource2') THEN N'adm' END;
SET #Table = CASE #Referral WHEN 'ReferralSource' THEN N'JobReferralSource'
WHEN 'ReferralSource2' THEN N'JobReferralSource2' END;
DECLARE #SQL nvarchar(MAX);
SET #SQL = N'UPDATE ' + QUOTENAME(#Schema) + N'.' + QUOTENAME(#Table) + NCHAR(13) + NCHAR(10) +
N'SET Active = #Active' + NCHAR(13) + NCHAR(10) +
N'WHERE Description= #Description;';
EXEC sp_executesql #SQL, N'#Description varchar(50), #Active bit', #Description = #Description, #Active = #Active;
END;

Conversion failed when converting the varchar value 'dynamic sql query' to data type int

I have a stored procedure for checking if row exist. I use this with ADO.NET for a dynamic query instead of having similar queries for all my tables.
CREATE PROCEDURE [dbo].[Row_Exist]
#TableName VARCHAR(50),
#ColumnName VARCHAR(50),
#RowId INT
AS
BEGIN
DECLARE #sqlQuery NVARCHAR(MAX) = ''
SET #sqlQuery = 'SELECT COUNT(1) as count FROM ' + #TableName + ' WHERE ' + #ColumnName + ' = ' + #RowId
EXEC(#sqlQuery)
END
If I execute this with a valid rowid, tablename, and columnname, I get the following error
Conversion failed when converting the varchar value SELECT COUNT(1) as count FROM Users WHERE UserID = to data type int.
This is because you try to concate int to varchar. Please try the below sql
CREATE PROCEDURE [dbo].[Row_Exist]
#TableName varchar(50),
#ColumnName varchar(50),
#RowId int
AS
BEGIN
DECLARE #sqlQuery NVARCHAR(MAX) = ''
SET #sqlQuery = 'SELECT COUNT(1) as count FROM ' + #TableName + ' WHERE ' + #ColumnName + ' = ' + CAST(#RowId AS VARCHAR(20))
EXEC(#sqlQuery)
END
Use parameters where you can. I tend to use REPLACE() to fill in the other values:
DECLARE #sqlQuery NVARCHAR(MAX) = '
SELECT COUNT(1) as count
FROM #TableName
WHERE #ColumnName = #RowId
';
SET #sqlQuery = REPLACE(REPLACE(#sqlQuery, '#TableName', quotename(#TableName)), '#ColumnName', quotename(#ColumnName));
EXEC sp_executesql #sqlQuery, N'#RowId int', #RowId=#RowId;

TSQL: Using 'Output' clause in dynamic SQL

I'm using an Output clause in my Insert statement which requires use of a Table Variable. I also want the Table name to be dynamic so I'm using dynamic SQL but it won't allow use of a Table Variable. I get the error Must declare the scalar variable "#InsertedId".
CREATE PROCEDURE sp_InsertPerson #Name varchar(50), #Table varchar(20) AS
DECLARE #InsertedId TABLE (Id int)
DECLARE #SQL nvarchar(200) = 'INSERT INTO ' + #Table + ' (Name) OUTPUT INSERTED.Id INTO ' + #InsertedId + ' VALUES (' + #Name + ')'
IF (#Name is not null AND #Name != '')
EXEC(#SQL)
SELECT Id FROM #InsertedId
How can I both use the Output clause and a dynamic Table name
First of all, do not use sp_ prefix to your stored procedure, cause it reserved to System stored procedures by MS, and can lead to performance issue and other problems (as it can be a habit). Use SysName datatype for the table name, and use QUOTENAME() function when you concatenate the string.
You need to declare your table in the DynamicSQL as
CREATE PROCEDURE InsertPerson
#Name varchar(50),
#Table SysName
AS
DECLARE #SQL NVARCHAR(MAX);
SET #SQL = N'DECLARE #IDs TABLE (ID INT);'+
'INSERT INTO ' +
QUOTENAME(#Table) +
' (Name) OUTPUT INSERTED.ID INTO #IDs VALUES(#Name);'+
'SELECT * FROM #IDs';
EXECUTE sp_executesql #SQL,
N'#Name VARCHAR(50)',
#Name;
Demo
Try this;
CREATE PROCEDURE sp_InsertPerson #Name varchar(50), #Table varchar(20) AS
DECLARE #SQL nvarchar(200) = ''
SET #SQL = #SQL + 'DECLARE #InsertedId TABLE (Id int)';
SET #SQL = #SQL + 'INSERT INTO ' + #Table + ' (Name) OUTPUT INSERTED.Id INTO #InsertedId (Id) VALUES (''' + #Name + ''')'
SET #SQL = #SQL + 'SELECT Id FROM #InsertedId'
IF (#Name is not null AND #Name != '')
EXEC(#SQL)

Sql Server Stored Procedure for adding columns to a table

I m trying to create a stored procedure that will add two columns onto the end of a table. The SP takes 3 inputs, a table name, a state, and a school year.
When I run the SP I get an error:
The name "CA" is not permitted in this context. Valid expressions are constants, constant expressions, and (in some contexts) variables. Column names are not permitted.
Here is my SP:
CREATE PROCEDURE sp_addScoolEnrollYear
#state nvarchar(2),
#shcoolYear nvarchar(15),
#tableName nvarchar(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
SET #Sql= N'alter table ' + quotename(#tableName) +
N'add StateEnrollID varchar(2) default ' + quotename(#state) + N'not null,
SchoolYearKey varchar(20) default ' + quotename(#shcoolYear) + N'not null'
EXECUTE sp_executesql #Sql
END
GO
This is how I execute:
[dbo].[sp_addScoolEnrollYear] N'CA', N'2014-2015' , N'[dbo].[test_copy]'
You were adding extra square brackets around the table name, and you need to use ' instead of square brackets around your strings, and some more spaces between words, and each column added needs to be a separate alter:
CREATE PROCEDURE sp_addScoolEnrollYear
#state nvarchar(2),
#shcoolYear nvarchar(15),
#tableName sysname
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
SET #Sql=N'alter table ' + #tablename
+ N' add StateEnrollID varchar(2) default ''' + #state + N''' not null;' +char(10)
+ N'alter table ' + #tablename
+ N' add SchoolYearKey varchar(20) default ''' + #shcoolYear + N''' not null;'
select #sql;
EXECUTE sp_executesql #Sql;
END
END
GO
exec [dbo].[sp_addScoolEnrollYear] N'CA', N'2014-2015' , N'[dbo].[test_copy]'
code generated:
alter table dbo.test_copy add StateEnrollID varchar(2) default 'CA' not null;
alter table dbo.test_copy add SchoolYearKey varchar(20) default '2014-2015' not null;
rextester demo: http://rextester.com/HEKC53724

Passing either null or a string to a stored procedure doesn't work (because of quotes?)

I am using a stored procedure below. For parameters called LockedByName and LockedByLoginName I want to pass either a string (which can contain spaces etc. - so I quote it with single quotes) or a NULL value.
The procedure works with strings but doesn't work with null value. I assume this is because it somehow silently fails because it cannot put the NULL value into quotes.
What could be the way to both keep the quotes and also keep the ability to use null value?
It similarly fails when the parameter is an empty string which would be fine to use too.
ALTER PROCEDURE [dbo].[ChangeLockFormStatus]
#FormID as int,
#LockedByName as nvarchar(50) = null,
#LockedByLoginName as nvarchar(50) = null,
#TableName as varchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #ActualTableName AS varchar(255)
SELECT #ActualTableName = QUOTENAME( TABLE_NAME )
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #TableName
DECLARE #sql AS NVARCHAR(MAX)
SELECT #sql = 'UPDATE ' + #ActualTableName
+ ' SET LockedByName=''' + #LockedByName + ''','
+ 'LockedByLoginName=''' + #LockedByLoginName
+ ''' WHERE [ID] = ' + CAST(#FormID AS VARCHAR(25)) + ';'
EXEC(#sql)
END
If you use sp_executesql, you can continue to use your parameters directly, rather than having to mangle them into the string. Something like:
ALTER PROCEDURE [dbo].[ChangeLockFormStatus]
#FormID as int,
#LockedByName as nvarchar(50) = null,
#LockedByLoginName as nvarchar(50) = null,
#TableName as varchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #ActualTableName AS varchar(255)
SELECT #ActualTableName = QUOTENAME( TABLE_NAME )
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #TableName
DECLARE #sql AS NVARCHAR(MAX)
SELECT #sql = 'UPDATE ' + #ActualTableName
+ ' SET LockedByName=#LockedByName,'
+ 'LockedByLoginName=#LockedByLoginName'
+ ' WHERE [ID] = #FormID;'
EXEC sp_executesql #sql,
N'#LockedByName nvarchar(50),#LockedByLoginName nvarchar(50),#FormID int',
#LockedByName,#LockedByLoginName,#FormID
END