Creating A Script To Replicate A Table And Its Contents? - sql

I know you can create a script to replicate a table using:
right click table > script table as > create to > new query editor window
But how can I generate a script that contains a bunch of insert commands for each row in the table?
Table1
Id1, Row1
Id2, Row2
Id3, Row3
Insert into Table1 values(Row1);
Insert into Table1 values(Row2);
Insert into Table1 values(Row3);

I ended up doing this
right click database > Tasks > Generate Scripts ... > selected the tables > in the advanced options I set "Types of data to script" to "Schema and data"

Select
'Insert into Table (
IntField1
StringField2
Column3)
values (' +
IntField1 + ',' +
+ '''' + StringField2 + ''',' +
Column2 + ')' as InsertQuery
From Table
Something like this, just remember if your string contains a single quote you will need to make sure you replace it like this replace(stringfield, '''', '''''')

So this isnt super pretty cuz I kind of took one of my sp's and hacked it up for this. But basically this will take any table and print a series of insert statements into a table called tbl_text (which you would need to create)
The arguments are the table name and the table ID from sysobjects
--this is how you get the tbl_id
SELECT id FROM sysobjects WHERE type = 'U' AND name = 'tablename'
CREATE PROCEDURE dbo.sp_export_table
#tblhdr varchar(100),
#tblID varchar(100)
AS
SET NOCOUNT ON
IF object_id('tempdb..##temptable') IS NOT NULL
BEGIN
DROP TABLE ##temptable
END
DECLARE #identity bit
DECLARE #typestmt nvarchar(100)
DECLARE #typeval int
DECLARE #rowstmt nvarchar(1000)
DECLARE #rowID varchar(50)
DECLARE #orderby nvarchar(100)
DECLARE #clmnstmt varchar(200)
DECLARE #clmnhdr varchar(50)
DECLARE #clmnstring varchar(1000)
DECLARE #valuestmt nvarchar(200)
DECLARE #valuestring nvarchar(3000)
DECLARE #value nvarchar(1000)
DECLARE #insertstmt varchar(1000)
DECLARE #params nvarchar(100)
DECLARE #param2 nvarchar(100)
SELECT #rowstmt = N'SELECT TOP 1 #inside_var = name FROM syscolumns WHERE id = ' + #tblID + ' ORDER BY colorder'
SELECT #params = N'#inside_var NVARCHAR(1000) OUTPUT'
EXEC sp_executesql #rowstmt, #params, #inside_var = #orderby OUTPUT
SELECT #rowstmt = 'SELECT *, ROW_NUMBER() OVER (ORDER BY ' + #orderby + ') AS row INTO ##temptable FROM ' + #tblhdr
exec(#rowstmt)
IF object_id('tempdb..##temptable') IS NOT NULL
BEGIN
DECLARE row_cursor CURSOR FOR
SELECT row FROM ##temptable
OPEN row_cursor
FETCH NEXT FROM row_cursor
INTO #rowID
--if table has identity and has records write identity_insert on
SET #identity = 0
IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE OBJECTPROPERTY(OBJECT_ID(TABLE_NAME),
'TableHasIdentity') = 1 AND TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME = #tblhdr) AND EXISTS(SELECT * FROM ##temptable)
BEGIN
SET #identity = 1
INSERT INTO dbo.tbl_text VALUES('SET IDENTITY_INSERT dbo.' + #tblhdr + ' ON')
END
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #clmnstmt = 'DECLARE column_cursor CURSOR FOR SELECT name FROM syscolumns WHERE id = ' + #tblID + ' ORDER BY colorder'
exec(#clmnstmt)
OPEN column_cursor
FETCH NEXT FROM column_cursor
INTO #clmnhdr
SELECT #clmnstring = '('
SELECT #valuestring = '('
WHILE ##FETCH_STATUS = 0
BEGIN
IF #clmnhdr <> 'row'
BEGIN
SELECT #clmnstring = #clmnstring + #clmnhdr + ','
SELECT #valuestmt = N'SELECT #inside_var = ' + #clmnhdr + ' FROM ##temptable WHERE row = ' + #rowID
EXEC sp_executesql #valuestmt, #params, #inside_var = #value OUTPUT
SELECT #typestmt = N'SELECT #inside_var2 = xtype FROM syscolumns WHERE name = ''' + #clmnhdr + ''' AND id = ' + #tblID
SELECT #param2 = N'#inside_var2 INT OUTPUT'
EXEC sp_executesql #typestmt, #param2, #inside_var2 = #typeval OUTPUT
IF #typeval NOT IN (48,52,56,59,60,62,104,108,122,127)
BEGIN
SET #value = REPLACE(#value,'''','''''')
SET #value = '''' + #value + ''''
SET #value = ISNULL(#value, '''''')
END
IF NOT (#typeval = 34)
BEGIN
SELECT #valuestring = #valuestring + #value + ','
END
ELSE
BEGIN
SELECT #valuestring = #valuestring + '''''' + ','
END
END
FETCH NEXT FROM column_cursor
INTO #clmnhdr
END
SET #clmnstring = LEFT(#clmnstring, LEN(#clmnstring) - 1)
SET #valuestring = LEFT(#valuestring, LEN(#valuestring) - 1)
INSERT INTO dbo.tbl_text VALUES('INSERT INTO dbo.' + #tblhdr + ' ' + #clmnstring + ') VALUES' + #valuestring + ')')
FETCH NEXT FROM row_cursor
INTO #rowID
CLOSE column_cursor
DEALLOCATE column_cursor
END
--if it wrote identity_insert on, turn it off
IF (#identity = 1)
BEGIN
INSERT INTO dbo.tbl_text VALUES('SET IDENTITY_INSERT dbo.' + #tblhdr + ' OFF')
END
CLOSE row_cursor
DEALLOCATE row_cursor
END
IF object_id('tempdb..##temptable') IS NOT NULL
BEGIN
DROP TABLE ##temptable
END
GO

If you've got an account on SSC, you can use the script I published last year. It works without cursors an it enables custom filtering.
http://www.sqlservercentral.com/scripts/Script+Data/65998/
Hope this helps

Assuming Row is an INT NOT NULL. You could write a SELECT statement that outputs SQL;
SELECT N'INSERT INTO Table1 VALUES (' + CAST(Row AS NVARCHAR(10)) + N');'
FROM Table1
Then output your results to text.

Related

SQL Server 2012 - Trigger: Operand type clash: int is incompatible with unique identifier

I am writing an audit trigger which saves every change occurred in the table in another table. But I receive this error when I am trying to alter the Users table:
Operand type clash: int is incompatible with unique identifier
The Users table contains a uniqueidentifier column, among others.
Here is the part of the code where the error occurs:
ALTER TRIGGER [dbo].[UsersLogger]
ON [dbo].[Users]
FOR INSERT, DELETE, UPDATE
AS
BEGIN
DECLARE #audit_oldvalue sql_variant;
DECLARE #audit_value sql_variant;
DECLARE #audit_field varchar(100);
DECLARE #sql nvarchar(max);
DECLARE #ParmDefinition nvarchar(max) ;
DECLARE #OutString varchar(max) ;
DECLARE #converted_uid nvarchar(50);
DECLARE #qid int ;
DECLARE #Cinfo VARBINARY(128)
SELECT #Cinfo = Context_Info()
IF #Cinfo = 0x55555
RETURN
DECLARE #Action as char(1);
SET #Action = (CASE WHEN EXISTS(SELECT * FROM INSERTED)
AND EXISTS(SELECT * FROM DELETED)
THEN 'U' -- Set Action to Updated.
ELSE NULL -- Skip. It may have been a "failed delete".
END)
SET #OutString = ''
SELECT *
INTO #tempTrigT
FROM
(SELECT *
FROM deleted
WHERE #Action IN ( 'U', 'D')) A
UNION
(SELECT *
FROM inserted
WHERE #Action = 'I')
SET #sql = ''
if #Action = 'U'
BEGIN
Select #sql = #sql + 'Case when IsNull(i.[' + Column_Name +
'],0) = IsNull(d.[' + Column_name + '],0) then ''''
else ' + quotename(Column_Name, char(39)) + ' + '',''' + ' end +'
from information_schema.columns
where table_name = 'Users' and column_name <>'rowguid' and column_name <>'modifieddate'
set #ParmDefinition = '#OutString varchar(max) OUTPUT'
set #sql = 'Select #OutString = '
+ Substring(#sql,1 , len(#sql) -1) +
' From dbo.Users i '
+ ' inner join #tempTrigT d on
i.id = d.id'
exec sp_executesql #sql, #ParmDefinition, #OutString OUT
END
DECLARE #Items VARCHAR(max)
set #Items = #OutString;
DECLARE #Item VARCHAR(50)
DECLARE #Pos INT
DECLARE #Loop BIT
SELECT #Loop = CASE WHEN LEN(#OutString) > 0 THEN 1 ELSE 0 END
WHILE (SELECT #Loop) = 1
BEGIN
SELECT #Pos = CHARINDEX(',', #OutString, 1)
IF #Pos > 0
BEGIN
SELECT #Item = SUBSTRING(#OutString, 1, #Pos - 1)
SELECT #OutString = SUBSTRING(#OutString, #Pos + 1, LEN(#OutString) - #Pos)
IF (TRY_CONVERT(UNIQUEIDENTIFIER, #Item) is not null)
begin
select #Item = convert(nvarchar(50), #Item)
end
If I had to guess, I'd blame it on
Select #sql = #sql + 'Case when IsNull(i.[' + Column_Name +
'],0) = IsNull(d.[' + Column_name + '],0) then ''''
else ' + quotename(Column_Name, char(39)) + ' + '',''' + ' end +'
from information_schema.columns
where table_name = 'Users' and column_name <>'rowguid' and column_name <>'modifieddate'
It's because you're doing an ISNULL on a UNIQUEIDENTIIFIER column and setting the value to an INT. You could change from ISNULL(i.[ColumnName], 0) to ISNULL(i.[ColumnName], '') however, that is assuming all the columns in your tables are string applicable datatypes. Otherwise, you could do some conditional logic on the replacement value for the ISNULL function by using the [DATA_TYPE] column in that table.

cursor loop - >while (##FETCH_STATUS=0) not going into loop

I have below code:
declare #prefix varchar(50)
set #prefix = 'schema1'
declare #TablesAndIdentifiers table (TableT0 varchar(50), TableX0 varchar(50), IdentifierT0 varchar(50), IdentifierX0 varchar(50))
insert into #TablesAndIdentifiers(TableT0, TableX0, IdentifierT0, IdentifierX0)
values
('table1', 'table2', 'external_Id', 'Key Details | External Id')
declare #TableT varchar(50)
declare #TableX varchar(50)
declare #IdentifierT varchar(50)
declare #IdentifierX varchar(50)
------------------------------------------OUTER LOOP------------------------------------------
declare #OuterCursor cursor
set #OuterCursor = cursor for select * from #TablesAndIdentifiers
open #OuterCursor
fetch next from #OuterCursor into #TableT, #TableX, #IdentifierT, #IdentifierX
while(##FETCH_STATUS = 0)
begin
declare #ColList2 table (ColListT varchar(50), ColListX varchar(50))
insert into #ColList2(ColListT,ColListX)
select ColListT, ColListX
from (
select COLUMN_NAME as ColListT, row_number() over (order by table_name) as r from INFORMATION_SCHEMA.Columns
where table_name = #TableT and COLUMN_NAME!=#IdentifierT) a
full outer join
(select COLUMN_NAME as ColListX, row_number() over (order by table_name) as r from INFORMATION_SCHEMA.Columns
where table_name = #TableX and COLUMN_NAME!=#IdentifierX) b
on a.r = b.r
--Declare and set variables containing the query which will insert the mismatch columns into a new table
--#sqlfull is a concatenation of #sqlpre, #sql, #sqlpost, #sqlwhere, #sqlpregroup, #sqlgroupstatement, #sqlpostgroup
--The reason for this is that #sql is the only part of the query we want to be contained in the loop - the others should run outside of the loop
declare #sqlpre varchar(max)
declare #sql varchar(max)
declare #sqlpost varchar(max)
declare #sqlgroupstatement varchar(max)
declare #sqlpostgroup varchar(max)
declare #sqlfull varchar(max)
set #sqlpre = 'select * from (select '
set #sql = ''
set #sqlpost = #IdentifierT + ' from '+#prefix+'.dbo.' +#TableX +' x inner join '+#prefix+'.dbo.' +#TableT + ' t on t.' +#IdentifierT + ' = x.[' + #IdentifierX +'])dt1 group by '
set #sqlgroupstatement = ''
set #sqlpostgroup = ' ' + #IdentifierT
declare #Cursor cursor, #ColListTvar varchar(100), #ColListXvar varchar(100)
set #Cursor = cursor for select * from #ColList2
open #Cursor
fetch next from #Cursor into #ColListTvar,#ColListXvar
Print 'Before While => ' + CAST(##FETCH_STATUS AS varchar(32))
while (##FETCH_STATUS = 0)
begin
Print 'Inside while -=> ' + CAST(##FETCH_STATUS AS varchar(32))
set #sql = #sql + 'case when t.' +#ColListTvar + ' != x.[' +#ColListXvar + '] then 1 else null end as ' + #ColListTvar+'_mismatch, '
set #sqlgroupstatement = #sqlgroupstatement + #ColListTvar+'_mismatch, '
fetch next from #Cursor into #ColListTvar,#ColListXvar
end
close #Cursor
Print 'After While => ' + CAST(##FETCH_STATUS AS varchar(32))
set #sqlfull = concat(#sqlpre,#sql,#sqlpost,#sqlgroupstatement,#sqlpostgroup)
print(#sqlfull)
--exec(#sqlfull)
declare #ColListMismatch varchar(max)
select #ColListMismatch = coalesce(#ColListMismatch+'_count,' ,'') + column_name
from INFORMATION_SCHEMA.COLUMNS where table_name = 'mismatches_' + #TableT and COLUMN_NAME!=#IdentifierT
-- The last column in the list won't get a '_count' in its name (but it needs it as the rest of the code assumes this is the naming convention)
-- See below for workaround to get round this
--Create table variable containing the list of mismatch columns (in which we want to count the non-nulls - non-null implies there has been a mismatch)
declare #ColListMismatchTable table (ColListM varchar(50))
insert into #ColListMismatchTable(ColListM)
select ColListM
from (select [COLUMN_NAME] as ColListM from INFORMATION_SCHEMA.Columns
where table_name = 'mismatches_'+#TableT and COLUMN_NAME!=#IdentifierT)dt1
--Declare variables for use in queries
declare #sqlpre2 varchar(max)
declare #sqlloop varchar(max)
declare #sqlpost2 varchar(max)
declare #sqlfull2 varchar(max)
-- Select counts from the transformation layer table and the XPLAN table; also select the count of the table produced as a result of the inner join between the two
-- If the migration has functioned correctly, these three counts should all be the same
set #sqlpre2 = 'select countXPLAN, countTransfLayer, countXPLAN-countTransfLayer as CountDiff, countMatchedIdentifiers, '
-- As mentioned above, the "+ #ColListMismatch + '_count into " part of the below is necessary to append the _count to the last variable
+ #ColListMismatch + '_count into '+#prefix+'.[dbo].report_' + #TableT + ' from '
set #sqlloop = ''
set #sqlpost2 = ' select * from ((select count(*) as countTransfLayer from '+#prefix+'.dbo.'+#TableT+')dt1 cross join (select count(*) as countXPLAN from '+#prefix+'.dbo.['+#TableX+'])dt2 cross join (select count(*) as countMatchedIdentifiers from '+#prefix+'.dbo.mismatches_'+#TableT+')dt4)'
------------------------------------------SECOND INNER LOOP------------------------------------------
--Use Cursor to create loop to produce counts for each column in mismatches_*
declare #Cursor2 cursor, #ColListMismatchvar varchar(50)
set #Cursor2 = cursor for select * from #ColListMismatchTable
open #Cursor2
fetch next from #Cursor2 into #ColListMismatchvar
while(##FETCH_STATUS = 0)
begin
-- Select all the counts of non-nulls
set #sqlloop = #sqlloop + '(select count(*) as '+ #ColListMismatchvar + '_count from mismatches_' + #TableT + ' where ' + #ColListMismatchvar + '=1)dt_' + #ColListMismatchvar + ' cross join '
fetch next from #Cursor2 into #ColListMismatchvar
end
-- Remove variables so that they can be reused by the next data entity
delete #ColListMismatchTable
select #ColListMismatch=null
close #Cursor2
print('in loop to execute sqlfull2')
set #sqlfull2 = concat(#sqlpre2,#sqlloop,#sqlpost2)
print(#sqlfull2)
-- exec(#sqlfull2)
print('executed sqlfull2')
fetch next from #OuterCursor into #TableT, #TableX, #IdentifierT, #IdentifierX
end
close #OuterCursor
out put of is:
(1 row(s) affected)
(0 row(s) affected)
Before While => -1
After While => -1
select * from (select external_Id from schema1.dbo.table22 x inner join schama1.dbo.table1 t on t.external_Id = x.[Key Details | External Id])dt1 group by external_Id
(0 row(s) affected)
(0 row(s) affected)
in loop to execute sqlfull2..
The problem i am facing code is not going into while loop of below code
declare #Cursor cursor, #ColListTvar varchar(100), #ColListXvar varchar(100)
set #Cursor = cursor for select * from #ColList2
open #Cursor
fetch next from #Cursor into #ColListTvar,#ColListXvar
Print 'Before While => ' + CAST(##FETCH_STATUS AS varchar(32))
while (##FETCH_STATUS = 0)
begin
Print 'Inside while -=> ' + CAST(##FETCH_STATUS AS varchar(32))
set #sql = #sql + 'case when t.' +#ColListTvar + ' != x.[' +#ColListXvar + '] then 1 else null end as ' + #ColListTvar+'_mismatch, '
set #sqlgroupstatement = #sqlgroupstatement + #ColListTvar+'_mismatch, '
fetch next from #Cursor into #ColListTvar,#ColListXvar
end
close #Cursor
Print 'After While => ' + CAST(##FETCH_STATUS AS varchar(32))
set #sqlfull = concat(#sqlpre,#sql,#sqlpost,#sqlgroupstatement,#sqlpostgroup)
print(#sqlfull)
--exec(#sqlfull)
any suggestions will be much appreciated.
Thanks in advance.
After lot of analysis i found that issue with
select ColListT, ColListX
from (
select COLUMN_NAME as ColListT, row_number() over (order by table_name) as r from INFORMATION_SCHEMA.Columns
where table_name = #TableT and COLUMN_NAME!=#IdentifierT) a
full outer join
(select COLUMN_NAME as ColListX, row_number() over (order by table_name) as r from INFORMATION_SCHEMA.Columns
where table_name = #TableX and COLUMN_NAME!=#IdentifierX) b
on a.r = b.r
Instead of Full outer join if i use inner join it worked.
There was issue with number of columns in 2 tables, one of table has less column than other, that's the reason it wasn't working properly.

Select table and column dynamically based on other table rows

I have following table and values,
Tb_name column_name1 column_name2
Citator_KTLO_CC Date_Created Date_Modified
Citator_KTLO_QA Date_Created Date_Modified
I want to select dynamically column from table, so the result is like this:
Select Date_Created,Date_Modified from Citator_KTLO_CC
and in next loop it will select for second row, like
Select Date_Created,Date_Modified from Citator_KTLO_QA
How can i do this by using dynamic sql ?
any example are appreciated.
here is an example of how to do this.
Since you dont post many info I just assume that the table containing all the tablenames is called 'tables'
Also this will only work if all tables have the same column types.
-- create a test table you dont need this
create table tables (tb_name varchar(100) primary key, field1 varchar(100), field2 varchar(100))
-- fill my test table you dont need this
insert into tables values ('table1', 'field1', 'field2')
insert into tables values ('table2', 'foo1', 'foo2')
insert into tables values ('table3', 'test1', 'test2')
-- this is the actual code you need, replace the names with your real names
declare #sql varchar(max) = ''
declare #tb_name varchar(100) = ''
declare #field1 varchar(100) = ''
declare #field2 varchar(100) = ''
declare myCursor cursor for
select tb_name, field1, field2 from tables -- dont know how your table is called
open myCursor
fetch next from myCursor into #tb_name, #field1, #field2
while ##FETCH_STATUS = 0
begin
set #sql = #sql + ' select ' + #field1 + ', ' + #field2 + ' from ' + #tb_name + ' union all '
fetch next from myCursor into #tb_name, #field1, #field2
end
close myCursor
deallocate myCursor
select #sql = left(#sql, len(#sql) - 10)
exec (#sql)
EDIT:
using a where clause is possible but things will get more complicated
declare #something date = getdate()
set #sql = #sql + ' select ' + #field1 + ', ' + #field2 + ' from ' + #tb_name + ' where ' + #field1 + ' = ' + #something + ' union all '
You can use the example above to build what you need just play with it.
EDIT:
using a where clause with a date format
declare #something date = getdate()
set #sql = #sql + ' select ' + #field1 + ', ' + #field2 + ' from ' + #tb_name + ' where ' + #field1 + ' = ''' + CONVERT(varchar(8), #something, 112) + ''' union all '
DECLARE #SQL VARCHAR(1000);
SET #SQL = '
SELECT *
FROM Citator_KTLO_CC
UNION ALL
SELECT *
FROM Citator_KTLO_QA;'
EXEC (#SQL);
How about something like this. If you've more than two cols, you can use dynamic sql to generate a list of cols to then generate more dynamic sql instead of hard coding.
DROP TABLE #Test
CREATE TABLE #Test
(Tb_name NVARCHAR(15),
column_name1 NVARCHAR(12),
column_name2 NVARCHAR(13));
INSERT INTO #Test VALUES
('Citator_KTLO_CC','Date_Created','Date_Modified'),
('Citator_KTLO_QA','Date_Created','Date_Modified');
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = (SELECT STUFF((SELECT ' UNION ALL SELECT ' + Cols + ' FROM '+TbL
FROM (SELECT QUOTENAME(Tb_name) TBL,
QUOTENAME(column_name1) + ', '+
QUOTENAME(column_name2) Cols
FROM #Test) Blah
FOR XML PATH('')),1,10,''))
PRINT #SQL
EXEC sys.sp_executesql #SQL
Try this..
For selecting one row if you are running in aloop
DECLARE #sql NVARCHAR(4000)
SELECT #sql = ' select ' + column_name_1 + ',' + column_name2 + ' from ' + Tb_name
FROM < yourtable >
EXEC (#sql)
OR
DECLARE #sql NVARCHAR(4000)
SELECT #sql = 'union all select ' + column_name_1 + ',' + column_name2 + ' from ' + Tb_name
FROM < yourtable >
SET #sql =stuff(#sql,1,10,'')
EXEC (#sql)
DECLARE #ColumnList1 VARCHAR(MAX) = '''''';
DECLARE #ColumnList2 VARCHAR(MAX) = '''''';
DECLARE #ColumnNameFromTable1 VARCHAR(50);
DECLARE #ColumnNameFromTable2 VARCHAR(50);
DECLARE MyCursor1 CURSOR
FOR
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Citator_KTLO_CC'
ORDER BY ORDINAL_POSITION
DECLARE MyCursor2 CURSOR
FOR
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Citator_KTLO_QA'
ORDER BY ORDINAL_POSITION
OPEN MyCursor1
OPEN MyCursor2
FETCH NEXT FROM MyCursor1 INTO #ColumnNameFromTable1;
WHILE ##FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM MyCursor2 INTO #ColumnNameFromTable2;
SET #ColumnList1 = #ColumnList1 + ',' + #ColumnNameFromTable1
SET #ColumnList2 = #ColumnList2 + ',' + #ColumnNameFromTable2
FETCH NEXT FROM MyCursor1 INTO #ColumnNameFromTable1;
END
CLOSE MyCursor1;
DEALLOCATE MyCursor1;
CLOSE MyCursor2;
DEALLOCATE MyCursor2;
EXEC ('SELECT ' + #ColumnList1 + ' FROM Citator_KTLO_CC UNION ALL SELECT ' +
#ColumnList2 + ' FROM Citator_KTLO_QA ')

Select columns based on values from any table(number of columns is variable) SQL

I have a following table:
Table 1
And I want to show only columns that have at least one value under 50:
Table 2
I need a stored procedure that does this. The trick is that I want to use it on multiple tables but the number of columns can vary from table to table.
Can this be done?
Wish this will have some help.
SET NOCOUNT ON
DECLARE
#tablename VARCHAR(50) = 'Table1',
#valuetocompare INT = 50,
#otherfields VARCHAR(100) = 'Date, Hour,';
DECLARE #t AS TABLE (cname VARCHAR(10), cvalue INT)
DECLARE #sql NVARCHAR(1000);
DECLARE #cname VARCHAR(128);
DECLARE c CURSOR
FOR
SELECT NAME
FROM sys.[columns] AS c
WHERE c.[object_id] = OBJECT_ID(#tablename)
;
OPEN c;
FETCH NEXT FROM c INTO #cname;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'select ''' + #cname + ''', ' + #cname + ' from ' + #tablename;
INSERT INTO #t
(
cname,
cvalue
)
EXECUTE (#sql);
FETCH NEXT FROM c INTO #cname;
END
CLOSE c;
DEALLOCATE c;
DECLARE #cnames VARCHAR(100) = '';
WITH dcnames AS (
SELECT DISTINCT cname
FROM #t
WHERE cvalue < #valuetocompare
)
SELECT #cnames = #cnames + cname + ','
FROM dcnames;
IF #cnames = ''
PRINT 'No column value is less than ' + CAST(#valuetocompare AS VARCHAR);
ELSE
BEGIN
SET #sql = 'select ' + #otherfields + LEFT(#cnames, LEN(#cnames) - 1) + ' from ' + #tablename;
EXECUTE (#sql);
END

How to avoid the cursor and what is the other way?

I am using the cursor in my stored procedure; I am hoping to remove the cursor from my SP. Please help me come up with a solution for how to avoid the cursor statement to normal update statement with dynamic.
Example Below:
Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'Test'(variable) and age = 18(variable)
Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'kumar'(variable) and age = 19(variable)
Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'babu'(variable) and age = 30(variable)
This is how my cursor will work. 300 Combination dynamically pick the data from table and update into the main table
I am trying to take out the cursor, and update statement should work similar to this, instead of writing 300 update statements, I want to write one update where all the 300 combinations should execute.
Below is my code which needs this solution:
BEGIN
DECLARE #Type VARCHAR(100)
DECLARE #TargetColumn VARCHAR(100)
DECLARE #SourceColumn VARCHAR(100)
DECLARE #SQL varchar(max)
DECLARE a_cursor CURSOR STATIC
FOR
SELECT [Type],[SourceColumn],[TargetColumn] FROM ref.tblEdsMap
GROUP BY [Type],[SourceColumn],[TargetColumn]
OPEN a_cursor
FETCH NEXT FROM a_cursor INTO #Type,#SourceColumn,#TargetColumn
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = 'UPDATE GCT SET GCT.' + #TargetColumn + ' = map.[TargetValue]
from EdsMap map
JOIN Table GCT
ON GCT.' + #SourceColumn + ' = map.[SourceValue]
where map.[Type]=''' + #Type + ''' and map.SourceColumn=''' + #SourceColumn+ ''''
Exec (#SQL)
PRINT #SQL
FETCH NEXT FROM a_cursor INTO #Type,#SourceColumn,#TargetColumn
END
CLOSE a_cursor
DEALLOCATE a_cursor
END
Rather than use an explicit cursor or a cursor cleverly disguised as a while loop, I prefer row concatenation operations for this type of problem.
DECLARE #cmd NVARCHAR(MAX) = N'';
SELECT #cmd += N'
UPDATE GCT
SET GCT.' + QUOTENAME(TargetColumn) + ' = map.TargetValue
FROM dbo.EdsMap AS map
INNER JOIN dbo.Table AS GCT
ON GCT.' + QUOTENAME(SourceColumn) + ' = map.SourceValue
WHERE map.[Type] = ''' + [Type] + '''
AND map.SourceColumn = ''' + [SourceColumn]+ ''';'
FROM ref.tblEdsMap
GROUP BY [Type], SourceColumn, TargetColumn;
EXEC sp_executesql #sql;
When I've done these in the past, I usually make up a transaction to encompass every update that's needed. Something like this:
CREATE TABLE #targets ([Type] VARCHAR(255),[SourceColumn] VARCHAR(255),[TargetColumn] VARCHAR(255));
INSERT INTO #targets
( [Type], [SourceColumn], [TargetColumn] )
SELECT [Type],[SourceColumn],[TargetColumn] FROM ref.tblEdsMap
GROUP BY [Type],[SourceColumn],[TargetColumn];
DECLARE #sql VARCHAR(MAX);
SET #sql = 'BEGIN TRAN' + CHAR(10) + CHAR(13);
SELECT #sql = #sql +
'UPDATE GCT SET GCT.' + [TargetColumn] + ' = map.[TargetValue]
from EdsMap map
JOIN Table GCT
ON GCT.' + [SourceColumn] + ' = map.[SourceValue]
where map.[Type]=''' + [Type] + ''' and map.SourceColumn=''' + [SourceColumn]+ ''';' + CHAR(10) + CHAR(13)
FROM #targets
SELECT #sql = #sql + 'COMMIT TRAN'
PRINT #sql
Exec (#SQL)
The update statements are still the same, i.e., you get one update per combination. But now you're running as one transaction batch. You could potentially be fancier with the dynamic SQL, so that you had just one update statement, but in my experience, it's too easy to get bad updates that way.
Doing it this way may not be any faster than a cursor. You'd have to test to be sure. With the examples where I've used this approach, it has generally been a faster approach.
Try using a table variable along with a WHILE loop instead, like so:
BEGIN
DECLARE #Type VARCHAR(100)
DECLARE #TargetColumn VARCHAR(100)
DECLARE #SourceColumn VARCHAR(100)
DECLARE #SQL varchar(max)
DECLARE #SomeTable TABLE
(
ID int IDENTITY (1, 1) PRIMARY KEY NOT NULL,
Type varchar(100),
SourceColumn varchar(100),
TargetColumn varchar(100)
)
DECLARE #Count int, #Max int
INSERT INTO #SomeTable (Type, SourceColumn, TargetColumn)
SELECT [Type],[SourceColumn],[TargetColumn]
FROM ref.tblEdsMap
GROUP BY [Type],[SourceColumn],[TargetColumn]
SELECT #Count = 1, #Max = COUNT(ID)
FROM #SomeTable
WHILE #Count <= #Max
BEGIN
SELECT
#Type = Type,
#SourceColumn = SourceColumn,
#TargetColumn = TargetColumn
FROM #SomeTable
WHERE ID = #Count
-- Your code
SET #SQL = 'UPDATE GCT SET GCT.' + #TargetColumn + ' = map.[TargetValue]
from EdsMap map
JOIN Table GCT
ON GCT.' + #SourceColumn + ' = map.[SourceValue]
where map.[Type]=''' + #Type + ''' and map.SourceColumn=''' + #SourceColumn+ ''''
Exec (#SQL)
PRINT #SQL
SET #Count = #Count + 1
END -- while
END