This is my stored procedure in SQL Server 2016:
CREATE PROCEDURE [USA_PHILIPS].[usp_stock]
#VCM INT,
#ID VARCHAR,
#SCHEMA_NAME VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
DROP TABLE IF EXISTS [USA_PHILIPS].[stock]
SELECT STOCKNUMBER,STOCKBOOKS
INTO [USA_PHILIPS].[stock]
FROM [USA_PHILIPS].[DMARTSTOCK]
WHERE VCM = #VCM
AND ID = #ID
END
How can I pass schema name as a parameter #SCHEMA_NAME?
And execute these statements as dynamic SQL:
DROP TABLE IF EXISTS [USA_PHILIPS].[stock]
Please help.
I would personally do it this way, injecting the value directing into the dynamic query. I also fix some of your data types:
CREATE PROCEDURE [USA_PHILIPS].[usp_stock] #VCM int,
#ID varchar(25), --Always define your varchar lengths
#SCHEMA_NAME sysname --Correct data type for object names
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL nvarchar(MAX),
#CRLF nchar(2) = NCHAR(13) + NCHAR(10)
SET #SQL = N'DROP TABLE IF EXISTS ' + QUOTENAME(#SCHEMA_NAME) + N'.[stock];' + #CRLF + #CRLF +
N'SELECT STOCKNUMBER,STOCKBOOKS' + #CRLF +
N'INTO ' + QUOTEMANE(#SCHEMA_NAME) + N'.[stock]' + #CRLF +
N'FROM [USA_PHILIPS].[DMARTSTOCK]' + #CRLF +
N'WHERE VCM=#VCM' + #CRLF +
N' AND ID = #ID;';
EXEC sys.sp_executesql #SQL, N'#VCM int, #ID varchar(25)', #VCM, #ID;
END;
All the code needs to be dynamic if an identifier is dynamic -- and you have to munge query strings:
CREATE PROCEDURE [USA_PHILIPS].[usp_stock] (
#VCM INT,
#ID VARCHAR(255),
#SCHEMA_NAME VARCHAR(50)
) AS
BEGIN
DECLARE #sql = NVARCHAR(MAX);
SET #sql = 'DROP TABLE IF EXISTS [SCHEMA].[stock]';
SET #sql = REPLACE(#sql, '[SCHEMA]', QUOTENAME(#SCHEMA_NAME));
EXEC sp_executeSQL #sql;
SET #sql = '
SELECT STOCKNUMBER, STOCKBOOKS
Into [SCHEMA].[stock]
from [USA_PHILIPS].[DMARTSTOCK]
WHERE VCM=#VCM AND ID = #ID';
SET #sql = REPLACE(#sql, '[SCHEMA]', QUOTENAME(#SCHEMA_NAME));
EXEC sp_executesql #sql,
N'#vcm INT, #id VARCHAR(255)',
#vcm=#vcm, #id=#id;
END;
Note some important changes to the query:
#ID has a length as an argument. This is important because the default varies by context and it might (well probably isn't) long enough for what you want.
I assume that you want the same table referenced in the DELETE as the INTO.
Pass the constant values as parameters.
Related
I have stored procedure where I have parameter with datatype sql_variant. This parameter is then converted and inserted into parameter that is nvarchar(MAX) datatype. Inserting dates and floats are working fine. Then as example inserting into varchar(60) cell doesn't seem to work and only inserts first letter. When I add SELECT statements for the parameters in stored procedure it shows after executing the information to be inserted correctly and it only fails the actual insertion to table.
How to insert whole nvarchar to varchar(60) or similar cell?
Here are important parts of the code without too much extra:
CREATE PROCEDURE proc_name
#param1 nvarchar(30),
#param2 nvarchar(30),
#param3 sql_variant
AS
BEGIN
SET NOCOUNT ON;
DECLARE #update_param nvarchar(MAX);
SET #update_param = CONVERT(nvarchar(MAX), #param3);
-- Lots of not important stuff here such as getting datatype from INFORMATION_SCHEMA
DECLARE #Sql nvarchar(MAX);
SET #Sql = N' DECLARE #variable ' + QUOTENAME(#datatype) + N' = #update_param '
+ N' UPDATE table_name'
+ N' SET ' + #param1 + N' = #variable '
+ N' WHERE something = ' + #param2
Exec sp_executesql #Sql, N'#update_param nvarchar(MAX)', #update_param
Adding SELECT #Sql to the procedure gives following result:
DECLARE #variable [varchar] = #update_param
UPDATE table_name
SET column_name = #variable
WHERE something = thingsome
When #param1 = column_name, #param2 = thingsome
Edit: I read multiple questions on this topic and they all told to declare nvarchar length. Here I have it declared as nvarchar(MAX).
Edit2: Added code bits.
Edit3: After adding code and help in comments the answer is that there is length undeclared for #datatype in #Sql
This doesn't answer the question at hand, however, the SP you have is open to injection. Raw string concatenation like that is a dangerous game to play. This is far safer:
CREATE PROCEDURE proc_name
#param1 nvarchar(30),
#param2 nvarchar(30),
#param3 sql_variant
AS
BEGIN
SET NOCOUNT ON;
DECLARE #update_param nvarchar(MAX);
SET #update_param = CONVERT(nvarchar(MAX), #param3);
-- Lots of not important stuff here such as getting datatype from INFORMATION_SCHEMA
DECLARE #Sql nvarchar(MAX);
SET #Sql = N' DECLARE #variable ' + QUOTENAME(#datatype) + N' = #dupdate_param' --Where is the value of #datatype coming from?
+ N' UPDATE table_name'
+ N' SET ' + QUOTENAME(#param1) + N' = #variable '
+ N' WHERE something = #dparam2;'
Exec sp_executesql #Sql, N'#dupdate_param nvarchar(MAX), #dparam2 nvarchar(30)',#dupdate_param = #update_param, #dparam = #param2;
GO
I am trying to execute this query:
declare #tablename varchar(50)
set #tablename = 'test'
select * from #tablename
This produces the following error:
Msg 1087, Level 16, State 1, Line 5
Must declare the table variable "#tablename".
What's the right way to have the table name populated dynamically?
For static queries, like the one in your question, table names and column names need to be static.
For dynamic queries, you should generate the full SQL dynamically, and use sp_executesql to execute it.
Here is an example of a script used to compare data between the same tables of different databases:
Static query:
SELECT * FROM [DB_ONE].[dbo].[ACTY]
EXCEPT
SELECT * FROM [DB_TWO].[dbo].[ACTY]
Since I want to easily change the name of table and schema, I have created this dynamic query:
declare #schema sysname;
declare #table sysname;
declare #query nvarchar(max);
set #schema = 'dbo'
set #table = 'ACTY'
set #query = '
SELECT * FROM [DB_ONE].' + QUOTENAME(#schema) + '.' + QUOTENAME(#table) + '
EXCEPT
SELECT * FROM [DB_TWO].' + QUOTENAME(#schema) + '.' + QUOTENAME(#table);
EXEC sp_executesql #query
Since dynamic queries have many details that need to be considered and they are hard to maintain, I recommend that you read: The curse and blessings of dynamic SQL
Change your last statement to this:
EXEC('SELECT * FROM ' + #tablename)
This is how I do mine in a stored procedure. The first block will declare the variable, and set the table name based on the current year and month name, in this case TEST_2012OCTOBER. I then check if it exists in the database already, and remove if it does. Then the next block will use a SELECT INTO statement to create the table and populate it with records from another table with parameters.
--DECLARE TABLE NAME VARIABLE DYNAMICALLY
DECLARE #table_name varchar(max)
SET #table_name =
(SELECT 'TEST_'
+ DATENAME(YEAR,GETDATE())
+ UPPER(DATENAME(MONTH,GETDATE())) )
--DROP THE TABLE IF IT ALREADY EXISTS
IF EXISTS(SELECT name
FROM sysobjects
WHERE name = #table_name AND xtype = 'U')
BEGIN
EXEC('drop table ' + #table_name)
END
--CREATES TABLE FROM DYNAMIC VARIABLE AND INSERTS ROWS FROM ANOTHER TABLE
EXEC('SELECT * INTO ' + #table_name + ' FROM dbo.MASTER WHERE STATUS_CD = ''A''')
Use:
CREATE PROCEDURE [dbo].[GetByName]
#TableName NVARCHAR(100)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #sSQL nvarchar(500);
SELECT #sSQL = N'SELECT * FROM' + QUOTENAME(#TableName);
EXEC sp_executesql #sSQL
END
You can't use a table name for a variable. You'd have to do this instead:
DECLARE #sqlCommand varchar(1000)
SET #sqlCommand = 'SELECT * from yourtable'
EXEC (#sqlCommand)
You'll need to generate the SQL content dynamically:
declare #tablename varchar(50)
set #tablename = 'test'
declare #sql varchar(500)
set #sql = 'select * from ' + #tablename
exec (#sql)
Use sp_executesql to execute any SQL, e.g.
DECLARE #tbl sysname,
#sql nvarchar(4000),
#params nvarchar(4000),
#count int
DECLARE tblcur CURSOR STATIC LOCAL FOR
SELECT object_name(id) FROM syscolumns WHERE name = 'LastUpdated'
ORDER BY 1
OPEN tblcur
WHILE 1 = 1
BEGIN
FETCH tblcur INTO #tbl
IF ##fetch_status <> 0
BREAK
SELECT #sql =
N' SELECT #cnt = COUNT(*) FROM dbo.' + quotename(#tbl) +
N' WHERE LastUpdated BETWEEN #fromdate AND ' +
N' coalesce(#todate, ''99991231'')'
SELECT #params = N'#fromdate datetime, ' +
N'#todate datetime = NULL, ' +
N'#cnt int OUTPUT'
EXEC sp_executesql #sql, #params, '20060101', #cnt = #count OUTPUT
PRINT #tbl + ': ' + convert(varchar(10), #count) + ' modified rows.'
END
DEALLOCATE tblcur
You need to use the SQL Server dynamic SQL:
DECLARE #table NVARCHAR(128),
#sql NVARCHAR(MAX);
SET #table = N'tableName';
SET #sql = N'SELECT * FROM ' + #table;
Use EXEC to execute any SQL:
EXEC (#sql)
Use EXEC sp_executesql to execute any SQL:
EXEC sp_executesql #sql;
Use EXECUTE sp_executesql to execute any SQL:
EXECUTE sp_executesql #sql
Declare #tablename varchar(50)
set #tablename = 'Your table Name'
EXEC('select * from ' + #tablename)
Also, you can use this...
DECLARE #SeqID varchar(150);
DECLARE #TableName varchar(150);
SET #TableName = (Select TableName from Table);
SET #SeqID = 'SELECT NEXT VALUE FOR ' + #TableName + '_Data'
exec (#SeqID)
Declare #fs_e int, #C_Tables CURSOR, #Table varchar(50)
SET #C_Tables = CURSOR FOR
select name from sysobjects where OBJECTPROPERTY(id, N'IsUserTable') = 1 AND name like 'TR_%'
OPEN #C_Tables
FETCH #C_Tables INTO #Table
SELECT #fs_e = sdec.fetch_Status FROM sys.dm_exec_cursors(0) as sdec where sdec.name = '#C_Tables'
WHILE ( #fs_e <> -1)
BEGIN
exec('Select * from ' + #Table)
FETCH #C_Tables INTO #Table
SELECT #fs_e = sdec.fetch_Status FROM sys.dm_exec_cursors(0) as sdec where sdec.name = '#C_Tables'
END
Lets say I want to write a stored prod
For SELECT
I found the above link for SELECT, but I want to do is for UPDATE:
SpUpdate #TableName varchar(50), #ColumnName varchar(50), #Value int, #Condition int
AS
BEGIN
UPDATE #Tablename
SET #ColumnName = #Value
Where PrimaryColName = #Condition
END
I know above code wont run. I know you can write a Dynamic code but I am not interested in Dynamic code. Can anyone help with different approch. Maybe using case statement or If statemens.
CREATE PROCEDURE SpUpdate
#TableName SYSNAME
, #ColumnName SYSNAME
, #Value INT
, #Condition INT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N' UPDATE ' + QUOTENAME(#TableName)
+ N' SET ' + QUOTENAME(#ColumnName) + N' = #Value '
+ N' WHERE PrimaryColName = #Condition '
EXECUTE sp_executesql #Sql
,N'#Value INT, #Condition INT'
,#Value
,#Condition
END
I want to import data from my Excel sheet into my SQL Server 2008 database.
I have an Excel sheet that contains different columns :
Service tag | marque | Type | Serial
FGT3456 | DELL | UC | Optiplex 760
and my table has the same structure, but instead of varchar values, I have foreign keys (the IDs)
Example (table material)
Service tag | marque| Type | Serial
FGT3456 | 1 | 18 | 27
What I want to do is to fetch into the column marque in the Excel sheet, get all the marque values, compare the values to those in my table, get all them IDs and in the end insert the Ids into my table material.
I tried this code but it's showing an error
Incorrect syntax near the keyword 'SELECT'.
Incorrect syntax near ')'.
Invalid object name 'SQL'.
This is my code
ALTER PROCEDURE [dbo].[spx_Import]
#SheetName varchar(20),
#FilePath varchar(100),
#HDR varchar(3),
#TableName varchar(50)
AS
BEGIN
DECLARE #SQL nvarchar(1000)
DECLARE #SQL1 nvarchar(1000)
DECLARE #SQL2 nvarchar(1000)
SET #SQL = 'SELECT idMarque FROM MarqueMateriel WHERE marque = SELECT (marque) FROM OPENDATASOURCE'
SET #SQL1 = 'INSERT INTO Material (Service tag) SELECT (service tag) FROM OPENDATASOURCE'
SET #SQL2 = 'INSERT INTO Material (MARQUE) SELECT * FROM '+#SQL''
SET #SQL = #SQL + '(''Microsoft.ACE.OLEDB.12.0'',''Data Source='
SET #SQL = #SQL + #FilePath + ';Extended Properties=''''Excel 12.0;HDR='
SET #SQL = #SQL + #HDR + ''''''')...['
SET #SQL = #SQL + #SheetName + ']'
SET #SQL1 = #SQL1 + '(''Microsoft.ACE.OLEDB.12.0'',''Data Source='
SET #SQL1 = #SQL1 + #FilePath + ';Extended Properties=''''Excel 12.0;HDR='
SET #SQL1 = #SQL1 + #HDR + ''''''')...['
SET #SQL1 = #SQL1 + #SheetName + ']'
SET #SQL1 = #SQL2 + '(''Microsoft.ACE.OLEDB.12.0'',''Data Source='
SET #SQL1 = #SQL2 + #FilePath + ';Extended Properties=''''Excel 12.0;HDR='
SET #SQL1 = #SQL2 + #HDR + ''''''')...['
SET #SQL1 = #SQL2 + #SheetName + ']'
EXEC sp_executesql #SQL
EXEC sp_executesql #SQL1
EXEC sp_executesql #SQL2
END
In the first query #SQL, I retrieve all IDs from the table Material where the name(marque) equals to those in the Excel sheet.
In the 2nd query, #SQL1, I insert the serviceTag values from the Excel sheet into the table
In the last one #SQL2, I insert into the table material the IDs retrieved from the first query
Is my logic correct ?? Is this how I should proceed ?? Please I need help !!
Try changing this line:
SET #SQL2 = 'INSERT INTO Material (MARQUE) SELECT * FROM '+#SQL''
To this - i.e. wrap the #SQL with brackets:
SET #SQL2 = 'INSERT INTO Material (MARQUE) SELECT * FROM (' + #SQL + ')'
I found the solution, it's quite easy and should've think of it from the first time . I imported all the data from my excel sheet into a temp table, and fetch into my mark table get all IDs and insert them directly into my material table.
This is how I achieved this
USE [AxaStock]
GO
ALTER PROCEDURE [dbo].[spx_Import]
#SheetName varchar(20),
#FilePath varchar(100),
#HDR varchar(3),
#TableName varchar(50)
AS
BEGIN
DECLARE #SQL nvarchar(1000)
DECLARE #QUERY nvarchar(1000)
SET #SQL = 'INSERT INTO ESSAIE (serviceTag, periodeGarantie, periodeLeasing, marque, designation, serie, entite, dateDG, nCommande) SELECT serviceTag, periodeGarantie, periodeLeasing, marque, designation, serie, entite, dateDG, nCommande FROM OPENDATASOURCE'
SET #QUERY = 'insert into Materiel (serviceTag, idMarque, idTypeMateriel, idSerieMateriel) select distinct serviceTag, idMarque, idTypeMateriel, '+
'idSerieMateriel from ESSAIEIMPORT ess, MarqueMateriel mm, Serie s, TypeMateriel tm where mm.marque=ess.marque and tm.nomType=ess.designation and '+
's.serieMateriel=ess.serie delete from ESSAIEIMPORT'
SET #SQL = #SQL + '(''Microsoft.ACE.OLEDB.12.0'',''Data Source='
SET #SQL = #SQL + #FilePath + ';Extended Properties=''''Excel 12.0;HDR='
SET #SQL = #SQL + #HDR + ''''''')...['
SET #SQL = #SQL + #SheetName + ']'
EXEC sp_executesql #SQL
EXEC sp_executesql #QUERY
END
I Have created a procedure which is:
CREATE PROCEDURE test.table_creation ( #ID INT )
AS
BEGIN
DECLARE #SQL VARCHAR(1000)
DECLARE #SchemaName VARCHAR(50)
DECLARE #TableName VARCHAR(100)
SELECT #SQL = 'Create Table ' + #SchemaName + '.' + #TableName + '('
SELECT #SQL = #SQL + 'ID int NOT NULL Primary Key, Name VarChar(10))'
EXEC (#SQL)
END
The problem here is I have to get the table name and Schema name from another table called sample. The query to get those is:
SELECT Source_Schema,Source_Table FROM sample where ID = 12
How do i use these values in the above procedure.
It seems a dubious requirement (you might want to read The Curse and Blessings of Dynamic SQL) but
CREATE PROCEDURE test.table_creation (#ID INT)
AS
BEGIN
DECLARE #SQL NVARCHAR(1000) /*Use nvarchar*/
DECLARE #SchemaName sysname /*Use sysname*/
DECLARE #TableName sysname
SELECT #SchemaName = Source_Schema,
#TableName = Source_Table
FROM sample
where ID = #ID
/*Use QUOTENAME*/
SELECT #SQL = 'Create Table ' + QUOTENAME(#SchemaName) + '.' +
QUOTENAME(#TableName) +
'(ID int NOT NULL Primary Key, Name VarChar(10))'
EXEC (#SQL)
END
SELECT
#SchemaName = Source_Schema,
#TableName = Source_Table
FROM sample where ID = 12