I need to add around 600 columns to an existing table for testing purpose
declare #counter int
set #counter = 1
while #counter < 601
begin
ALTER TABLE Info ADD column+#counter varchar(max);
set #counter = #counter + 1
end
The column name should looks like column1,column2....column600
As this is purely for testing a quick and dirty way is to do this:
declare #counter int
set #counter = 1
declare #sql varchar(2000)
while #counter < 601
begin
Set #Sql = 'ALTER TABLE Info ADD column'+convert(varchar(10),#counter)+ ' varchar(max)'
Exec (#Sql)
set #counter = #counter + 1
end
Although I have to wonder why you would want 600 columns in a table
Use dynamic sql execution-
SET #str = 'ALTER TABLE Info ADD column' + CAST(#counter as varchar(5)) + ' varchar(max)';
EXEC ( #str );
GO
use Exec function:
Declare #SQL VarChar(1000)
Declare #vary varchar(100)
Declare #final varchar(1000)
SELECT #SQL = 'ALTER TABLE '
SELECT #SQL = #SQL + #TableName
select #vary = 'add column ' + id
select #final = #sql + #vary
Exec ( #final)
GO
Related
I am trying to execute some logic on a remote server using dynamic SQL, but when I set the dynamic SQL and try to call it nothing happens.. If I call the execution without making the execution dynamic it works without issue.
Not sure if what I am trying to do is allowed when passing OUTPUT values but figured I would see if anyone has any thoughts
DECLARE #sqlserver NVARCHAR(MAX) = ''
DECLARE #DBName NVARCHAR(MAX) = ''
DECLARE #parms NVARCHAR(MAX) = N'#output INT OUT', #output INT, #sql NVARCHAR(MAX) = '
;WITH DuplicateStatusCodes AS (
SELECT CodeTypeID FROM EDDSDBO.Code WHERE Name = ''Master'' OR Name = ''Unique'' OR Name = ''Duplicate''
)
SELECT ROW_NUMBER() OVER (ORDER BY CodeTypeID) RN, CodeTypeID INTO #temp
FROM DuplicateStatusCodes
GROUP BY CodeTypeID
HAVING COUNT(CodeTypeID) = 3
DECLARE #count INT = (SELECT COUNT(1) FROM #temp)
DECLARE #ctr INT = 1;
IF #count > 0
BEGIN
WHILE #ctr <= #count BEGIN
DECLARE #parms NVARCHAR(MAX) = N''#inneroutput INT OUT'';
DECLARE #inneroutput INT
DECLARE #codeartifact INT = (SELECT CodeTypeID FROM #temp WHERE RN <= 1 * #ctr and RN > 1 * (#ctr - 1))
DECLARE #duplicatestatuscheck NVARCHAR(MAX) = ''SELECT #inneroutput = COUNT(1) FROM eddsdbo.codeartifact_''+CAST(#codeartifact AS VARCHAR)+''''
EXEC sys.sp_executesql #duplicatestatuscheck, #parms, #inneroutput OUT
SELECT #output = #inneroutput
IF #inneroutput > 0
BREAK;
SET #ctr = #ctr + 1;
END
END
ELSE
BEGIN
SELECT #output = ''0''
END
'
DECLARE #linksql NVARCHAR(MAX) = '
DECLARE #sql NVARCHAR(MAX)
DECLARE #parms NVARCHAR(MAX) = N''#output INT OUT''
EXEC '+QUOTENAME(#sqlserver)+'.'+QUOTENAME(#DBName)+'.sys.sp_executesql #sql, #parms, #output = #output OUT'
--This does not work
EXEC sp_executesql #linksql, #parms, #output = #output
PRINT #output
--This works fine
EXEC [RemoteServerName].[DatabaseName].sys.sp_executesql #sql, #parms, #output = #output OUT ```
Appreciate any help
you would need to use OPENROWSET. Something like this:
DECLARE #ServerName VARCHAR(255) = '...'
,#DatabaseName VARCHAR(255) = '...'
,#Pwd VARCHAR(255) = '...'
,#UID VARCHAR(255) = '...'
,#Name VARCHAR(255) = 'Master'
DECLARE #connect varchar(max) = '''Server=' + #ServerName + ';database=' + #DatabaseName + ';Uid=' + #UID + ';Pwd=' + #Pwd + ';'''
declare #sqlstring varchar(max) = 'SET ANSI_NULLS OFF; SET ANSI_WARNINGS OFF;
SELECT CodeTypeID FROM EDDSDBO.Code WHERE Name = ''''' + #Name + ''''' '
declare #TheExecutableStr varchar(max) = '
SELECT *
FROM OPENROWSET(''SQLNCLI'', ' + #connect + ',
''' + #sqlstring + ''')'
SELECT #TheExecutableStr
--EXEC(#TheExecutableStr)
Please note you have to count single quote very diligently, hence SELECT #TheExecutableStr. It is for debugging purposes. You can view the query to be executed and actually copy/paste and execute before uncommenting last statement.
Hope it helps.
just noticed, you have sys.sp_executesql within sys.sp_executesql which might be problematic. you might need to find a way to refactor the code.
I have n tables that is unknown before runtime with tablename always being tablename1, tablename2... tablenameN. The first column of each table is always Name. The challenge is to change that column name in each table to Name1, Name2.. NameN. I know I should be using sp_rename and a loop. Having trouble building up the query, I'm pretty new to SQL. Help would be appreciated. THanks
This should do the rename:
DECLARE #counter INT;
DECLARE #tableName NVARCHAR(100);
DECLARE #columnName NVARCHAR(100);
DECLARE #newColumnName NVARCHAR(100);
SET #counter = 1;
WHILE #counter < 65536
BEGIN
SET #tableName = 'tableName' + CAST(#counter AS NVARCHAR)
IF EXISTS(SELECT * FROM sys.tables WHERE name = #tableName)
BEGIN
SET #columnName = #tableName + N'.name';
SET #newColumnName = N'name' + CAST(#counter AS NVARCHAR);
EXEC sp_rename #objname=#columnName, #newName=#newColumnName;
END
ELSE
BEGIN
SET #counter = 65536
END
SET #counter = #counter + 1
END
It's a bit crude though.. and renames only 65535 tables and full amount only when there's none missing in between.
Uncomment sql_exec when you're sure it does what you're expecting :)
DECLARE #TableName sysname, #ColName sysname
DECLARE #num sysname
DECLARE #sql nvarchar(4000)
DECLARE cTables CURSOR FOR SELECT name from dbo.sysobjects where Category = 0 AND type NOT IN (N'F', N'FN', N'IF', N'TF', N'P', N'TR', N'V', N'K') AND name like 'tablename%'
OPEN cTables
FETCH NEXT FROM cTables INTO #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #num = SUBSTRING(#Tablename, 10, 5)
SET #sql = N'sp_RENAME ''' + #TableName + '.[Name]'' , ''[Name' + #num + ']'', ''COLUMN'''
PRINT #sql
-- EXEC sp_sqlexec #sql
FETCH NEXT FROM cTables INTO #TableName
END
CLOSE cTables;
DEALLOCATE cTables;
Here's a SP - give it a try ;-)
CREATE PROCEDURE dbo.Rename
(
#n INT
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #Stmt NVARCHAR(MAX)
DECLARE #i INT
DECLARE #tabname NVARCHAR(MAX)
DECLARE #colname NVARCHAR(MAX)
SET #i = 1
WHILE #i <= #n
BEGIN
SET #tabname = N'tablename' + CAST(#i AS NVARCHAR(MAX))
SET #colname = N'name' + CAST(#i AS NVARCHAR(MAX))
IF EXISTS(SELECT TOP 1 1 FROM sys.tables t WHERE t.name = #tabname)
BEGIN
SET #Stmt = N'EXEC sp_rename ''' + #tabname + '.[name]'', ''' + #colname +''',''COLUMN'''
--PRINT #Stmt
EXEC sp_executesql #Stmt
END
SET #i = #i + 1
END
END
is it possible to do dynamic declarations?
I will explain: I have a table COLUMNAMES:
ID|Name
1|Country
2|City
3|District
4|Neighbourhood
For each record in that table I would like to do something like:
declare #i int = 1
declare #number int
set #number = (SELECT count(*) FROM COLUMNNAMES)
While #i <= #number
BEGIN
Execute ('Declare column' + #i +'varchar(25)')
Execute ('set column' + #i +' = (Select NAME from COLUMNAMES where id = ' + #i)
set #i = #i + 1
END
The idea is that I get a list of variables (strings) that I can use to create SELECT statements with dynamic table-aliases:
Execute ('Select SOMECOLUMN as ' + #columname + #i +', ANOTHERCOLUMN as ' + #columname + #i +', ATHIRDCOLUMN as ' + #columname + #i + ' FROM SOMETABLE')
Can this be done? If so, how?
Each Execute function as a different session.
So, in order to declare the variable, all the code must be in one Execute function.
No you can't declare variables like this, but you can use a temporary table with the data filled in.
Here is some help, but it is not a whole solution, just an idea what you can do instead of the not working declaration:
Create Table #ColumnNames(
NAME varchar(64)
)
While #i <= #number
BEGIN
INSERT INTO #ColumNames
Select NAME from COLUMNAMES where id = #i
set #i = #i + 1
END
DECLARE #Columns varchar(max)
SET #Columns = ''
SElECT #Columns = #Columns + NAME + ', '
FROM #ColumNames
This is not complete solution but a direction . you need to get the value 'SomeColumn' dynamically someway ,likely the way you are getting the aliases in the below solution.
declare #i int = 1
declare #number INT
DECLARE #ColName VARCHAR(25)
DECLARE #SQL VARCHAR(4000)=''
DECLARE #ColumnsWithAlias VARCHAR(4000) = ''
set #number = (SELECT count(*) FROM COLUMNNAMES)
While #i <= #number
BEGIN
Select #ColName= NAME from COLUMNAMES where id = #i)
SET #ColumnsWithAlias =#ColumnsWithAlias + 'SomeColumn'+ ' AS '+ #ColName + ' , '
set #i = #i + 1
END
SET #SQL= 'SELECT '#ColumnsWithAlias+' FROM TableName'
EXECUTE(#SQL)
I had wrote this below stored procedure and getting incorrect statement.
ALTER PROCEDURE dbo.[Counter]
#TableName VARCHAR(100)
AS
BEGIN
DECLARE #Counter INT
DECLARE #SQLQ VARCHAR(200)
SET NOCOUNT ON;
--SET #TableName = 'Member';
SET #SQLQ = 'SELECT COUNT(*) FROM dbo.[' + #TableName + ']';
--Preparing the above sql syntax into a new statement(get_counter).
--Getting an error here I had googled the prepare statement but don't know why facing this error.
PREPARE get_counter FROM #SQLQ;
#Counter = EXEC get_counter; -- here #resutl gets the value of the count.#TableName
DEALLOCATE PREPARE get_counter; -- removing the statement from the memory.
END
Then I had wrote another one:
ALTER PROCEDURE dbo.[Counter]
#TableName VARCHAR(100)
AS
BEGIN
DECLARE #Counter INT
DECLARE #SQLQ VARCHAR(200)
SET NOCOUNT ON;
--SET #TableName = 'Member';
SET #SQLQ = 'SELECT COUNT(*) FROM dbo.[' + #TableName + ']';
--Preparing the above sql syntax into a new statement(get_counter).
Execute #SQLQ; -- here #resutl gets the value of the count.#TableName
--DEALLOCATE PREPARE get_counter; -- removing the statement from the memory.
Return #Counter;
END
It is running fine but I can't get the result in the Counter , anyone please help me(I know that I haven't assigned any value to the counter but if I do I get error).
After your answer martin I had replace my code with yours now its :
ALTER PROCEDURE dbo.[Counter] #SchemaName SYSNAME = 'dbo' , #TableName SYSNAME
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQLQ NVARCHAR(1000)
DECLARE #Counter INT;
SET #SQLQ = 'SELECT #Counter = COUNT(*) FROM ' +
Quotename(#SchemaName) + '.' + Quotename(#TableName);
EXEC sp_executesql
#SQLQ ,
N'#Counter INT OUTPUT',
#Counter = #Counter OUTPUT
Return SELECT #Counter
END
Now I had retrieved it .
ALTER PROCEDURE dbo.[CreateBusinessCode]
#MemberID bigint,
#len int,
#RewardAccountID bigint,
#ConnectionStatusID tinyint,
#Assign smalldatetime
AS
BEGIN
SET NOCOUNT ON;
DECLARE #counter INT
EXEC #counter = dbo.Counter 'dbo','member';
Select #counter;
END
You should use SYSNAME for object identifiers and Quotename rather than concatenating the square brackets yourself.
ALTER PROCEDURE dbo.[Counter] #TableName SYSNAME,
#SchemaName SYSNAME = 'dbo'
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQLQ NVARCHAR(1000)
DECLARE #Counter INT;
SET #SQLQ = 'SELECT #Counter = COUNT(*) FROM ' +
Quotename(#SchemaName) + '.' + Quotename(#TableName);
EXEC sp_executesql
#SQLQ ,
N'#Counter INT OUTPUT',
#Counter = #Counter OUTPUT
SELECT #Counter
END
In SQL Server, if you want to get a result into a variable, you have two choices.
The first is to use cursors.
The second is to do dynamic SQL:
declare #sql varchar(max) = whatever;
declare #cnt int;
declare #cntTable table as (cnt int);
insert into #cntTable
exec(#sql);
select #cnt = t.cnt
from #cntTable
It is cumbersome, but one or the other does work.
try this one.It doesnt query the actual table but will provide you the count of rows.This is better way if you have large tables and you need approximate count.
ALTER PROCEDURE dbo.[Counter]
#TableName VARCHAR(100)
AS
begin
declare #objectid int,#counter int
select #objectid = object_id from sys.all_objects where name = #tablename and schema_id=SCHEMA_ID('dbo')
select #counter = sum(rows) from sys.partitions where object_id= #objectid
and index_id in (0,1)
select #counter
end
go
I have a procedure and the code looks like this:
ALTER PROCEDURE [dbo].[usp_Gen_Proc]
(#ID INT )
AS
Begin
IF OBJECT_ID('tempdb..#procedure') IS NOT NULL
DROP TABLE #procedure
DECLARE #Name VARCHAR(100)
DECLARE #SQL VARCHAR(MAX)
DECLARE #Script VARCHAR(MAX),
#DB VARCHAR(100),
#Schema VARCHAR(100),
#Proc_Name VARCHAR(max),
#BR CHAR(2)
SET #BR = CHAR(10)+ CHAR(13)
SET NOCOUNT ON
SELECT #Name= [Procedure_Name] FROM dbo.datsource
WHERE [ID] = #ID
SELECT #Proc_Name = PARSENAME(#Name, 1) ,
#Schema = PARSENAME(#Name, 2) ,
#DB = PARSENAME(#Name, 3)
CREATE TABLE #procedure ( script VARCHAR(MAX) )
EXEC('INSERT INTO #procedure(script)
SELECT definition FROM '+#DB+'.sys.all_sql_modules sq
WHERE sq.object_id = (SELECT object_id FROM '+#DB+'.sys.objects
WHERE type = ''P'' AND name = '''+#Proc_Name+''' ) ')
SET #Script = ' Use ' +#BR +#DB + #BR+ ' Go' +#BR
SELECT #Script = #Script+script
FROM #procedure
DECLARE #pos INT =7500
SELECT #pos=CHARINDEX(CHAR(13)+CHAR(10),#script,#pos)
PRINT SUBSTRING(#Script,1,#Pos)
DECLARE #Counter INT
SET #Counter = 0
DECLARE #TotalPrints INT
SET #TotalPrints = ( LEN(#script) / 8000 )
WHILE #Counter < #TotalPrints
BEGIN
SET #Counter = #Counter + 1
PRINT SUBSTRING(#script,#pos+1,7500)
SET #pos = #pos+7500
SELECT #pos=CHARINDEX(CHAR(13)+CHAR(10),#script,#pos)
END
END
Basically what the procedure is doing it just prints the procedure code. But the problem I am facing is when I am printing it i am loosing some characters in between.
Can anyone let me know where I am going wrong?
Why do you want to print ?
Why you don't do a select with the script, put it in xml if you want to see everything.
Select Convert(xml, #script)
EDIT :
between you don't need to do +1
PRINT SUBSTRING(#script,#pos,7500)