I have a problem with treating table name as variable as I need to put the results to different table each month automatically (without using any advanced procedures to make this query dynamic). Can somebody help me to modify this code and make it work?
declare #exp_dte as date;
set #exp_dte='2015-12-31';
print (#exp_dte);
declare #tab_mth as nvarchar(max);
set #tab_mth=year(#exp_dte)*100+month(#exp_dte);
print (#tab_mth);
declare #tab_name as nvarchar(max)
set #tab_name='mis_anl.dbo.BIK_' + #tab_mth
print (#tab_name);
IF OBJECT_ID (N'#tab_name', N'U') IS NOT NULL
begin
drop table #tab_name
end
select distinct
*
into #tab_name
from table_x
You have to use dynamic SQL to set name at runtime:
DECLARE #exp_dte DATE = '2015-12-31';
DECLARE #tab_name SYSNAME = '[dbo].' + QUOTENAME('BIK_' + FORMAT(#exp_dte, 'yyyyMM'));
IF OBJECT_ID (#tab_name, N'U') IS NOT NULL
BEGIN
EXEC('DROP TABLE' + #tab_name);
END
DECLARE #sql NVARCHAR(MAX) = N'SELECT DISTINCT *
INTO #tab_name
FROM table_x';
SET #sql = REPLACE(#sql, '#tab_name', #tab_name);
EXEC [dbo].[sp_executesql] #sql;
LiveDemo
Remarks:
Try to be more conscise
You could use FORMAT to get yyyyMM (SQL Server 2012+)
Always QUOTENAME generated identifiers to avoid SQL Injection attacks
I strongly recommend to read The Curse and Blessings of Dynamic SQL especially CREATE TABLE #tbl.
use dynamic sql ,you cant user table names as variables
declare #exp_dte as date;
set #exp_dte='2015-12-31';
declare #tab_mth as nvarchar(max);
set #tab_mth=year(#exp_dte)*100+month(#exp_dte);
declare #tab_name as nvarchar(max)
set #tab_name='mis_anl.dbo.BIK_' + #tab_mth
declare #sql1 nvarchar(max)
set #sql1='drop table '+#tab_name;
IF exists(select 1 from information_schema.tables where table_name=#tab_name)
begin
exec(#sql1);
end
declare #sql nvarchar(max)
set #sql='
select distinct
*
into '+#tab_name+'
from table_x'
exec (#sql)
Related
I'm trying to create a generic script to copy data from one database to another and I've written this script.
USE TargetDatabase;
DECLARE #SourceDatabase NVARCHAR(100);
DECLARE #TargetDatabase NVARCHAR(100);
DECLARE #SourceTable NVARCHAR(100);
DECLARE #TargetTable NVARCHAR(100);
DECLARE #var NVARCHAR(MAX);
SET #SourceDatabase = 'SourceDB'
SET #TargetDatabase = 'TargetDB'
SET #SourceTable = 'SourceTable'
SET #TargetTable = 'TargetTable'
set #var = (SELECT STRING_AGG (QUOTENAME(COLUMN_NAME), ',') from
#TargetDatabase.INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = #TargetTable);
As you can see below, in the INSERT statement I'm giving Table Name, Column Name and Values as a variable. This is where I'm having problems, so basically I don't know how to evaluate these variables #var, #SourceTable, #TargetTable.
INSERT INTO #TargetTable (SELECT #Var)
SELECT * FROM #SourceTable
I'm stuck here and I don't know how to solve this issue. Can any one explain how I can solve this problem?
There are many other ways to run a dynamic query but here is one way you can run your query as per your requirements.
declare #table nvarchar(50)
declare #query nvarchar(500)
set #table = 'Test'
set #query='insert into [' +#table+ '] Select * from [' +#table+ ']';
Exec sp_executesql #query;
I have a language table and I want to select aliases from that table according to the specified language.
ALTER PROCEDURE sp_executesql
(#parameter1 NVARCHAR(MAX)
,#parameter2 NVARCHAR(MAX)
,#code NVARCHAR(MAX),#language NVARCHAR(MAX))
DECLARE #sql NVARCHAR(MAX)
SET #sql = 'SELECT '+#parameter1+' AS (SELECT #language FROM Languages WHERE code=somecolumn) '+#paramter2+' AS (SELECT #language FROM Languages WHERE code='+#code+') FROM mytable'
EDIT:
in Stored Procedure, I need something like that.
Thanks for answers..
You cannot use a subquery to build an alias in that way, you would need to use dynamic sql to do this.
DECLARE #language NVARCHAR(255) -- or whatever type your field is
SELECT #language=language FROM Languages WHERE code=#code
DECLARE #sql NVARCHAR(MAX) = 'SELECT ' + #parameter1 + ' AS ' + QUOTENAME(#language) + ' FROM MyTable'
EXEC sp_executesql #sql
(Note the inclusion of QUOTENAME around the alias - this is a safety feature in case of your alias names having invalid characters.)
You can repeat the code above for the second parameter inside your stored procedure.
Try this:
CREATE PROCEDURE sp_NameOfSP
(#parameter1 NVARCHAR(MAX)
,#parameter2 NVARCHAR(MAX)
,#code NVARCHAR(MAX)
,#language NVARCHAR(MAX))
AS
BEGIN
DECLARE #sql NVARCHAR(MAX)
SELECT TOP(1) #language=LanguageColumn FROM Languages WHERE code=somecolumn
SET #sql = 'SELECT '+#parameter1+' AS '+#language+', '
SELECT TOP(1) #language=LanguageColumn FROM Languages WHERE code=#code
SET #sql=#sql+#paramter2+' AS '+#language+' FROM mytable'
EXEC(#SQL)
END
Replace LanguageColumn with proper column name from Languages table
I'm trying to append table name dynamically to SQL Server stored procedure, but I get an error:
couldn't find the stored procedure 's'
Code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[atest_demo_sp]
#name varchar(10)
AS
BEGIN
Declare #tname nvarchar
Declare #sql nvarchar
set #tname = #name
Set #sql = 'select * from ' + convert(varchar(10), #tname)
-- select #sql
execute sp_executesql #sql
END
You need to explicitly define a length for your string variables!
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[atest_demo_sp]
#name varchar(10)
AS
BEGIN
Declare #tname nvarchar(200) -- DEFINE A LENGTH HERE !!!
Declare #sql nvarchar(200) -- DEFINE A LENGTH HERE !!!
set #tname = #name
Set #sql = N'select * from ' + convert(nvarchar(10), #tname)
-- select #sql
execute sp_executesql #sql
END
Otherwise, your variables #tname and #sql will be exactly 1 character long! Probably not what you want!
See this blog post for more details: Bad habits to kick : declaring VARCHAR without (length)
Also, as a side note: either pick varchar (non-Unicode), or use nvarchar (Unicode) - but don't mix the two. And if you use nvarchar, you should always use the N'...' notation for assigning string literals.
The issue with the set #tname = #name, no need to assign the varchar to nvarchar here. Avoid the #tname variable and directly use #name in the SET statement since it is already varchar.
Hope the #name's first character only assigning to #tname. Also need to define the #sql to some length.
Use the below statement, it will work:
Declare #sql varchar(100);
Set #sql = 'select * from ' + #name
I have a query that I want to be able to use across database schemas. Right now it is written so that I need to replace the schema in several places of the query. How do I set that up as a variable so that all I need to do is change it in one place?
You can do this with Dynamic SQL:
DECLARE #sql VARCHAR(MAX)
,#schema VARCHAR(255) = 'dbo'
SET #sql = 'SELECT *
FROM '+#schema+'.yourTable
'
EXEC (#sql)
You could use this in a cursor to loop through schema's:
DECLARE #Iterator varchar(255)
,#strSQL varchar(MAX)
DECLARE xyz CURSOR
FOR
--Select stuff to iterate over
SELECT name
FROM sys.schemas
OPEN xyz
FETCH NEXT FROM xyz
INTO #Iterator
WHILE ##FETCH_STATUS = 0
BEGIN
--Do stuff
SET #strSQL = 'SELECT *
FROM '+#Iterator+'.yourTable
'
Exec (#strSQL)
FETCH NEXT FROM xyz
INTO #Iterator
END
CLOSE xyz
DEALLOCATE xyz
GO
To test your dynamic SQL statements, you can change EXEC to PRINT and ensure that the resulting query is as you intended.
Synonyms might be the answer to your question.
You can use dynamic SQL. Here is an example -
DECLARE #Column varchar(25)
DECLARE #sqlStmt varchar(max)
SET #Column = 'MyColumn'
SET #sqlStmt = N'SELECT ' + #Column + ' FROM MyTable'
EXEC (#sqlStmt)
Hi I am writing a large stored procedure, which creates a dynamic report table, of n columns in size, the first 6 are constant the remainder depend on a few arguments passed to the procedure to create the table with the required columns.
The problem that I am having is with the following TSQL
DECLARE #columnname VARCHAR(50)
SET #columnname = 'on_' + #description
IF NOT EXISTS(SELECT * FROM syscolumns WHERE id = OBJECT_ID('reports')
AND NAME = #columnname)
BEGIN
ALTER TABLE reports ADD #columnname VARCHAR(50) NULL
END
I am getting syntax errors with this at the #columnname in the ALTER TABLE statement of the above code.
Also as I am new to this, I am not sure if this is the best way to do this, or if there are better ways in TSQL to generate the required dynamic table.
Try this:
declare #sql nvarchar(100)
set #sql = 'ALTER TABLE reports ADD '+ #columnname+' VARCHAR(50) NULL'
exec sp_executesql #sql
Try
DECLARE #columnname VARCHAR(50)
SET #columnname = '[on_' + #description +']'
IF NOT EXISTS(SELECT * FROM syscolumns WHERE id = OBJECT_ID('reports')
AND NAME = #columnname)
BEGIN
ALTER TABLE reports ADD #columnname VARCHAR(50) NULL
END
Cannot get around having to do it dynamically I believe so change your BEGIN block to something like this:
DECLARE #sql VARCHAR(8000)
BEGIN
SET #sql = 'ALTER TABLE Table_1 ADD '+#columnname+' VARCHAR(50) NULL'
EXEC(#sql)
END