Requirement : We used to get min 10 to 50 table names (from different schema's and servers(using linked server ) as refresh requests from Prod to Test or Dev environment on regular basis.
Ex: We have 3 schema's called dbo,Schema1 and Schema 2 in prod where as in other environments we have different schema names such as schemaC and SchmaD etc.
For this I am using the below script to get the table names in single quotations.
Step 1 :
Declare #String Varchar(8000) = 'schemaname.table1,schemaname.table2,schemname.table1s45k'
Set #String = '''' + Replace(#String, ',', ''',''') + ''''
Select #String
Step 2 : I will backup the existing tables data in our bkpdata base table.
Step 3 : I will truncate the backedup tables
Step 4: I will move the data from Production to dev / test environment with help of linked server ex: in dev box
Insert into databasename.schemaname.tablename select * from linkedservername.schemaname.tablename
It would be great if we can get dynamic SQL code with parameters facility as Tablenames , databasename,linkedservername and schema name facility.
Any other options also highly appreciated.
adding additional details :
Declare #String Varchar(8000) = 'schema1.rnd,schema2.test'
Set #String = '''' + Replace(#String, ',', ''',''') + ''''
declare #Strings table (names varchar(max))
insert into #strings
select #String
select 'Truncate Table '+''+ name from sys.tables where name in (select name from #strings )
It will display the results as Truncate table Tablename . So I don't want to execute the results and it has to execute the output itself .I guess dynamic SQL Will help.
--#String contains location where to(db.schema.tablenm) copy and where from(servevr.dbb.schema.tablenm)
--At the end of each copy and copy from need to provide , as delimeter
--copy to and copy from is seprated by |
Declare #String Varchar(8000) =
'db.schema.tablenm|servevr.dbb.schema.tablenm,
db1.schema1.tablenm1|servevr1.db1.schema1.tablenm1,
db2.schema2.tablenm2|servevr2.db2.schema2.tablenm2,
'
Declare #str Varchar(8000)
Declare #execStr Varchar(8000)
Declare #delimeterocc int
Declare #delimeterSer int
declare #start int
set #start=0
Set #delimeterocc=charindex(',',#String)
While(#delimeterocc>0)
begin
set #str=SUBSTRING(#String,#start,len(#string)-(len(#String)-#delimeterocc)-#start)
Set #delimeterSer=charindex('|',#str)
print 'Insert Into ' + SUBSTRING(#str,1,#delimeterSer-1) + ' Select * From '+ SUBSTRING(#str,#delimeterSer+1,len(#str)-#delimeterSer)
Set #start=#delimeterocc+1
Set #delimeterocc=charindex(',',#String,#start)
end
Related
I create a Script sql-server that returns two html code from two different views that I created. The problem is that, when I'm running the .sql file (scrip) in sqlcmd, the html result in the file output is incomplete (obs. If I execute in management studio, the result in html is complete).
I have no idea how to proceed. I think in Oracle set long is used, but I don't know in Microsoft SQL Server.
--CODE IN SQLCMD
--SQLCMD -S LOCALHOST\SQLEXPRESS -i C:\checklist_sql\check_sql\checklist.sql -o C:\checklist_sql\lib\resultado.html
SET NOCOUNT ON;
---------ROCEDUR TO HTML----
GO
create PROCEDURE [dbo].[SqlTableToHtml] (
#TABLENAME NVARCHAR(500),
#OUTPUT NVARCHAR(MAX) OUTPUT,
#TBL_STYLE NVARCHAR(1024) = '',
#TD_STYLE NVARCHAR(1024) = '',
#HDR_STYLE NVARCHAR(1024) = '')
AS
-- Description
-- Stored Procedure to take an arbitraty temporary table and return
-- the equivalent HTML string .
-- #exec_str stores the dynamic SQL Query
-- #ParmDefinition stores the parameter definition for the dynamic SQL
DECLARE #exec_str NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
--We need to use Dynamic SQL at this point so we can expand the input table name parameter
SET #exec_str= N'
DECLARE #exec_str NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
--Make a copy of the original table adding an indexing columnWe need to add an index column to the table to facilitate sorting so we can maintain the
--original table order as we iterate through adding HTML tags to the table fields.
--New column called CustColHTML_ID (unlikely to be used by someone else!)
--
select CustColHTML_ID=0,* INTO #CustomTable2HTML FROM ' + #TABLENAME + '
--Now alter the table to add the auto-incrementing index. This will facilitate row finding
DECLARE #COUNTER INT
SET #COUNTER=0
UPDATE #CustomTable2HTML SET #COUNTER = CustColHTML_ID=#COUNTER+1
-- #HTMLROWS will store all the rows in HTML format
-- #ROW will store each HTML row as fields on each row are iterated through
-- using dymamic SQL and a cursor
-- #FIELDS will store the header row for the HTML Table
DECLARE #HTMLROWS NVARCHAR(MAX) DECLARE #FIELDS NVARCHAR(MAX)
SET #HTMLROWS='''' DECLARE #ROW NVARCHAR(MAX)
-- Create the first HTML row for the table (the table header). Ignore our indexing column!
SET #FIELDS=''<tr>''
SELECT #FIELDS=COALESCE(#FIELDS, '' '','''')+''<th ' + #HDR_STYLE + '>'' + name + ''</th>''
FROM tempdb.sys.Columns
WHERE object_id=object_id(''tempdb..#CustomTable2HTML'')
AND name not like ''CustColHTML_ID''
SET #FIELDS=#FIELDS + ''</tr>''
-- #ColumnName stores the column name as found by the table cursor
-- #maxrows is a count of the rows in the table, and #rownum is for marking the
-- ''current'' row whilst processing
DECLARE #ColumnName NVARCHAR(500)
DECLARE #maxrows INT
DECLARE #rownum INT
--Find row count of our temporary table
SELECT #maxrows=count(*) FROM #CustomTable2HTML
--Create a cursor which will look through all the column names specified in the temporary table
--but exclude the index column we added (CustColHTML_ID)
DECLARE col CURSOR FOR
SELECT name FROM tempdb.sys.Columns
WHERE object_id=object_id(''tempdb..#CustomTable2HTML'')
AND name not like ''CustColHTML_ID''
ORDER BY column_id ASC
--For each row, generate dymanic SQL which requests the each column name in turn by
--iterating through a cursor
SET #rowNum=0
SET #ParmDefinition=N''#ROWOUT NVARCHAR(MAX) OUTPUT,#rowNum_IN INT''
While #rowNum < #maxrows
BEGIN
SET #HTMLROWS=#HTMLROWS + ''<tr>''
SET #rowNum=#rowNum +1
OPEN col
FETCH NEXT FROM col INTO #ColumnName
WHILE ##FETCH_STATUS=0
BEGIN
--Get nth row from table
SET #exec_str=''SELECT #ROWOUT=(select COALESCE(['' + #ColumnName + ''], '''''''') AS ['' + #ColumnName + ''] from #CustomTable2HTML where CustColHTML_ID=#rowNum_IN)''
EXEC sp_executesql
#exec_str,
#ParmDefinition,
#ROWOUT=#ROW OUTPUT,
#rowNum_IN=#rownum
SET #HTMLROWS =#HTMLROWS + ''<td ' + #TD_STYLE + '>'' + #ROW + ''</td>''
FETCH NEXT FROM col INTO #ColumnName
END
CLOSE col
SET #HTMLROWS=#HTMLROWS + ''</tr>''
END
SET #OUTPUT=''''
IF #maxrows>0
SET #OUTPUT= ''<table ' + #TBL_STYLE + '>'' + #FIELDS + #HTMLROWS + ''</table>''
DEALLOCATE col
'
DECLARE #ParamDefinition nvarchar(max)
SET #ParamDefinition=N'#OUTPUT NVARCHAR(MAX) OUTPUT'
--Execute Dynamic SQL. HTML table is stored in #OUTPUT which is passed back up (as it's
--a parameter to this SP)
EXEC sp_executesql #exec_str,
#ParamDefinition,
#OUTPUT=#OUTPUT OUTPUT
RETURN 1;
---- VIEW VERSION SQL--
GO
create view versao_sql as
SELECT Convert(nvarchar(30),SERVERPROPERTY('MachineName')) AS [NOME DA MAQUINA] ,
Convert(nvarchar(30),SERVERPROPERTY('InstanceName')) AS [INSTANCIA] ,
Convert(nvarchar(30),SERVERPROPERTY('ProductVersion')) AS [PRODUCT VERSION],
Convert(nvarchar(30),SERVERPROPERTY('ProductLevel')) AS [PRODUCT LEVEL] ,
Convert(nvarchar(30),SERVERPROPERTY('Edition')) AS [EDIÇÃO] ,
( CASE SERVERPROPERTY('EngineEdition')
WHEN 1 THEN 'Personal or Desktop'
WHEN 2 THEN 'Standard'
WHEN 3 THEN 'Enterprise'
else ''
END ) AS [ENGINE TYPE] ,
Convert(nvarchar(30),SERVERPROPERTY('LicenseType')) AS [TIPO DE LICENÇA] ,
convert(nvarchar(30), SERVERPROPERTY('NumLicenses')) AS [LICENÇAS] ,
( CASE SERVERPROPERTY('IsIntegratedSecurityOnly')
WHEN 0 THEN 'Mista'
WHEN 1 THEN 'Integrada'
else ''
END ) AS [SOMENTE SEGURANÇA INTEGRADA] ,
convert(nvarchar(30),SERVERPROPERTY('Collation')) AS [COLLATION] ,
( CASE SERVERPROPERTY('IsClustered')
WHEN 0 THEN 'Nao'
WHEN 1 THEN 'Sim'
END ) AS [CLUSTER];
------INFO INSTANCE--
GO
create view info_instancia as
select 'VERSAO DO CHECK LIST' as DESCRICAO,'2.2.6' as VALOR
union all
select 'NOME DO SERVIDOR' as DESCRICAO, CAST(##SERVERNAME as nvarchar) as VALOR
union all
select 'IP DO SERVIDOR' as DESCRICAO, CAST(CONNECTIONPROPERTY('local_net_address') as nvarchar) as VALOR
union all
select 'NOME DA INSTANCIA' as DESCRICAO, CAST(SERVERPROPERTY('InstanceName') as nvarchar) as VALOR
union all
select 'NLS_CHARACTERSET' as DESCRICAO, CAST(SERVERPROPERTY('Collation') as nvarchar) as VALOR
union all
select 'VERSAO SQL SERVER' as DESCRICAO, CAST(##VERSION as nvarchar) as VALOR
union all
select 'DATA DE HOJE' as DESCRICAO, CAST(GETDATE() as nvarchar) as VALOR;
-- RUNNING PROCEDURE FOR EACH VIEW
GO
--SQL VERSION
declare #html nvarchar(max)
exec SqlTableToHtml 'versao_sql', #html output, 'style="table:"border=1 width=65%"', '', 'style="scope=col"'
select #html;
GO
--INSTANCE SQL
declare #html nvarchar(max)
exec SqlTableToHtml 'info_instancia', #html output, 'style="table:"border=1 width=65%"', '', 'style="scope=col"'
select #html;
----DROPINGS----
GO
drop view versao_sql;
GO
drop view info_instancia;
GO
DROP PROCEDURE SqlTableToHtml;
The other day I found a great stored procedure in this symantec link that converts the results of a TSQL table into an HTML table. Without any CSS parameters, the result works great. I tend to send tons of emails with SQL server results, so this is very helpful.
Now that I was able to make it work, I'm trying to add some style to the table. The problem is that I'm not sure how sending the CSS class as parameter works.
For example, here's how I should call the SP:
EXEC dbo.CustomTable2HTMLv3 'Buffy',#HTML1 OUTPUT,'class="horizontal"',0
The problem is that I have no idea where the CSS class horizontal comes from. In the link I can see the actual CSS, but how does the stored procedure read this?
The css looks like this:
table.horizontal tr:first-child {
background-color: Gray!important;
font-weight: bold;
color: #fff;
}
And this is the stored procedure:
CREATE PROCEDURE [dbo].[CustomTable2HTMLv3] (
#TABLENAME NVARCHAR(500),
#OUTPUT NVARCHAR(MAX) OUTPUT,
#TBL_STYLE NVARCHAR(1024) = '',
#ALIGNMENT INT =0 )
AS
-- Author: Ian Atkin (ian.atkin#ict.ox.ac.uk)
-- Description
-- Stored Procedure to take an arbitraty temporary table and return
-- the equivalent HTML string .
-- Version History
-- 1.0 - v1 Release For Symantec Connect
-- 3.0 - v3 Release for Symantec connect.
-- Table to be outputed both horizonally and vertically. IsNull used
-- on cell value output to prevent NULLs creaping into HTML string
-- #exec_str stores the dynamic SQL Query
-- #ParmDefinition stores the parameter definition for the dynamic SQL
DECLARE #exec_str NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
IF #ALIGNMENT=0
BEGIN
--We need to use Dynamic SQL at this point so we can expand the input table name parameter
SET #exec_str= N'
DECLARE #exec_str NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #DEBUG INT
SET #DEBUG=0
IF #DEBUG=1 Print ''Table2HTML -Horizontal alignment''
--Make a copy of the original table adding an indexing column. We need to add an index column to the table to facilitate sorting so we can maintain the
--original table order as we iterate through adding HTML tags to the table fields.
--New column called CustColHTML_ID (unlikely to be used by someone else!)
--
select CustColHTML_ID=0,* INTO #CustomTable2HTML FROM ' + #TABLENAME + '
IF #DEBUG=1 PRINT ''Created temporary custom table''
--Now alter the table to add the auto-incrementing index. This will facilitate row finding
DECLARE #COUNTER INT
SET #COUNTER=0
UPDATE #CustomTable2HTML SET #COUNTER = CustColHTML_ID=#COUNTER+1
IF #DEBUG=1 PRINT ''Added counter column to custom table''
-- #HTMLROWS will store all the rows in HTML format
-- #ROW will store each HTML row as fields on each row are iterated through
-- using dymamic SQL and a cursor
-- #FIELDS will store the header row for the HTML Table
DECLARE #HTMLROWS NVARCHAR(MAX) DECLARE #FIELDS NVARCHAR(MAX)
SET #HTMLROWS='''' DECLARE #ROW NVARCHAR(MAX)
-- Create the first HTML row for the table (the table header). Ignore our indexing column!
SELECT #FIELDS=COALESCE(#FIELDS, '' '','''')+''<td>'' + name + ''</td>''
FROM tempdb.sys.Columns
WHERE object_id=object_id(''tempdb..#CustomTable2HTML'')
AND name not like ''CustColHTML_ID''
SET #FIELDS=#FIELDS + ''</tr>''
IF #DEBUG=1 PRINT ''table fields: '' + #FIELDS
-- #ColumnName stores the column name as found by the table cursor
-- #maxrows is a count of the rows in the table, and #rownum is for marking the
-- ''current'' row whilst processing
DECLARE #ColumnName NVARCHAR(500)
DECLARE #maxrows INT
DECLARE #rownum INT
--Find row count of our temporary table
SELECT #maxrows=count(*) FROM #CustomTable2HTML
--Create a cursor which will look through all the column names specified in the temporary table
--but exclude the index column we added (CustColHTML_ID)
DECLARE col CURSOR FOR
SELECT name FROM tempdb.sys.Columns
WHERE object_id=object_id(''tempdb..#CustomTable2HTML'')
AND name not like ''CustColHTML_ID''
ORDER BY column_id ASC
--For each row, generate dymanic SQL which requests the each column name in turn by
--iterating through a cursor
SET #rowNum=1
SET #ParmDefinition=N''#ROWOUT NVARCHAR(MAX) OUTPUT,#rowNum_IN INT''
While #rowNum <= #maxrows
BEGIN
SET #HTMLROWS=#HTMLROWS + ''<tr>''
OPEN col
FETCH NEXT FROM col INTO #ColumnName
IF #DEBUG=1 Print ''#ColumnName: '' + #ColumnName
WHILE ##FETCH_STATUS=0
BEGIN
--Get nth row from table
--SET #exec_str=''SELECT #ROWOUT=(select top 1 ['' + #ColumnName + ''] from (select top '' + cast(#rownum as varchar) + '' * from #CustomTable2HTML order by CustColHTML_ID ASC) xxx order by CustColHTML_ID DESC)''
SET #exec_str=''SELECT #ROWOUT=(select ['' + #ColumnName + ''] from #CustomTable2HTML where CustColHTML_ID=#rowNum_IN)''
IF #DEBUG=1 PRINT ''#exec_str: '' + #exec_str
EXEC sp_executesql
#exec_str,
#ParmDefinition,
#ROWOUT=#ROW OUTPUT,
#rowNum_IN=#rownum
IF #DEBUG=1 SELECT #ROW as ''#Row''
SET #HTMLROWS =#HTMLROWS + ''<td>'' + IsNull(#ROW,'''') + ''</td>''
FETCH NEXT FROM col INTO #ColumnName
END
CLOSE col
SET #rowNum=#rowNum +1
SET #HTMLROWS=#HTMLROWS + ''</tr>''
END
SET #OUTPUT=''''
IF #maxrows>0
SET #OUTPUT= ''<table ' + #TBL_STYLE + '>'' + #FIELDS + #HTMLROWS + ''</table>''
DEALLOCATE col
'
END
ELSE
BEGIN
--This is the SQL String for table columns to be aligned on the vertical
--So we select a table column, and then iterate through all the rows for that column, this forming
--one row of our html table.
SET #exec_str= N'
DECLARE #exec_str NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #DEBUG INT
SET #DEBUG=0
IF #DEBUG=1 Print ''Table2HTML -Vertical alignment''
--Make a copy of the original table adding an indexing column. We need to add an index column to the table to facilitate sorting so we can maintain the
--original table order as we iterate through adding HTML tags to the table fields.
--New column called CustColHTML_ID (unlikely to be used by someone else!)
--
select CustColHTML_ID=0,* INTO #CustomTable2HTML FROM ' + #TABLENAME + '
IF #DEBUG=1 PRINT ''CustomTable2HTMLv2: Modfied temporary table''
--Now alter the table to add the auto-incrementing index. This will facilitate row finding
DECLARE #COUNTER INT
SET #COUNTER=0
UPDATE #CustomTable2HTML SET #COUNTER = CustColHTML_ID=#COUNTER+1
-- #HTMLROWS will store all the rows in HTML format
-- #ROW will store each HTML row as fields on each row are iterated through
-- using dymamic SQL and a cursor
DECLARE #HTMLROWS NVARCHAR(MAX)
DECLARE #ROW NVARCHAR(MAX)
SET #HTMLROWS=''''
-- #ColumnName stores the column name as found by the table cursor
-- #maxrows is a count of the rows in the table
DECLARE #ColumnName NVARCHAR(500)
DECLARE #maxrows INT
--Find row count of our temporary table
--This is used here purely to see if we have any data to output
SELECT #maxrows=count(*) FROM #CustomTable2HTML
--Create a cursor which will iterate through all the column names in the temporary table
--(excepting the one we added above)
DECLARE col CURSOR FOR
SELECT name FROM tempdb.sys.Columns
WHERE object_id=object_id(''tempdb..#CustomTable2HTML'')
AND name not like ''CustColHTML_ID''
ORDER BY column_id ASC
--For each **HTML** row, we need to for each iterate through each table column as the outer loop.
--Once the column name is identified, we use Coalesc to combine all the column values into a single string.
SET #ParmDefinition=N''#COLOUT NVARCHAR(MAX) OUTPUT''
OPEN col
FETCH NEXT FROM col INTO #ColumnName
WHILE ##FETCH_STATUS=0
BEGIN
--Using current column name, grab all column values and combine into an HTML cell string using COALESCE
SET #ROW=''''
SET #exec_str='' SELECT #COLOUT=COALESCE(#COLOUT + ''''</td>'''','''''''') + ''''<td>'''' + Cast(IsNull(['' + #ColumnName + ''],'''''''') as nvarchar(max)) from #CustomTable2HTML ''
IF #DEBUG=1 PRINT ''#exec_str: '' + #exec_str
EXEC sp_executesql
#exec_str,
#ParmDefinition,
#COLOUT=#ROW OUTPUT
SET #HTMLROWS =#HTMLROWS + ''<tr>'' + ''<td>'' + #ColumnName + ''</td>'' + #ROW + ''</tr>''
IF #DEBUG=1 SELECT #ROW as ''Current Row''
IF #DEBUG=1 SELECT #HTMLROWS as ''HTML so far..''
FETCH NEXT FROM col INTO #ColumnName
END
CLOSE col
SET #OUTPUT=''''
IF #maxrows>0
SET #OUTPUT= ''<table ' + #TBL_STYLE + '>'' + #HTMLROWS + ''</table>''
DEALLOCATE col
'
END
DECLARE #ParamDefinition nvarchar(max)
SET #ParamDefinition=N'#OUTPUT NVARCHAR(MAX) OUTPUT'
--Execute Dynamic SQL. HTML table is stored in #OUTPUT which is passed back up (as it's
--a parameter to this SP)
EXEC sp_executesql #exec_str,
#ParamDefinition,
#OUTPUT=#OUTPUT OUTPUT
RETURN 1
So, the following is mentioned in the link you have provided:
"In order to help you style your tables, in the zip download I've also
included an HTML file which has an embedded style sheet in the head
element."
So, if you open the html file they mention there, you will see they have declared the style inside the html itself.
You can only create the table via SQL and if you like, attach the class name passing it as a parameter, BUT you will need to generate a full HTML file containing the CSS (or having it referenced, it doesn't matter) in order to have your table styled.
As I mentioned in the comment, if the table will be printed horizontally or vertically is only defined by the #alignment attribute, not by the CSS class. (You can see this in the stored procedure code)
I have a table called Std_Components which acts like an index for list of components with associated tables. The column AssociatedTable holds the name of table that actually contains the component data.
Please check images below -
Here is table data for Std_SteeringPumps
I am trying to create a stored procedure that will copy Std_Components table as well as all associated tables with new name. For ex. Lets say if i provided 001 as a parameter to this stored procedure i should be able create new tables like C001_Components, C001_SteeringPumps and so on.
This is what I have done so far:
ALTER PROCEDURE [dbo].[sgi_sp_CreateTablesForNewCompany]
-- Add the parameters for the stored procedure here
#CompanyId varchar(5)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- declare variables
declare #qry as varchar(2000)
declare #compTblName as varchar(100)
set #compTblName = 'C'+#companyId +'_Components'
-- Check if table already exists
IF object_id(#compTblName) is not null
return
-- Create main component index table by copying standard component table --
set #qry = 'Select * into '+#compTblName+' From Std_Components;';
--print #qry
--execute (#qry)
set #qry =#qry + 'Update C'+#companyId +'_Components Set AssociatedTable=''C'+#companyId +'''+substring(AssociatedTable,4,200);';
--print #qry
--exec #qry
-- Create all child tables --
Select * Into #TempTbl From dbo.Std_Components
Declare #Id int
While (Select Count(*) From #TempTbl) > 0
Begin
declare #rowTableName as varchar(50)
declare #compNewTbl as varchar(50)
Select Top 1 #rowTableName=AssociatedTable, #Id = Id From #TempTbl
set #compNewTbl = 'C'+#companyId + substring(#rowTableName,4,200);
set #qry = #qry + 'Select * into '+#compNewTbl+' From ' + #rowTableName + ';'
--print #qry
--exec #qry
Delete #TempTbl Where Id = #Id
End
print #qry
exec #qry
END
Here is the output of the print statement for the query it generates -
Select * into C001_Components From Std_Components;
Update C001_Components Set AssociatedTable='C001'+substring(AssociatedTable,4,200);
Select * into C001_SteeringPumps From Std_SteeringPumps;
But when the stored procedure is executed, I get the following error -
Msg 203, Level 16, State 2, Procedure sgi_sp_CreateTablesForNewCompany, Line 56
The name 'Select * into C001_Components From Std_Components;Update C001_Components Set AssociatedTable='C001'+substring(AssociatedTable,4,200);Select * into C001_SteeringPumps From Std_SteeringPumps;' is not a valid identifier.
Can anybody help me out resolve this issue.
Thanks for sharing your time and wisdom.
The error you're getting is because the EXEC statement (the last line of the stored procedure) needs to have brackets around the #qry variable so that it becomes
exec(#qry)
Without the brackets it's treating the entire SQL string as stored procedure name.
The non valid indentifier is around the AssociatedTable part
Set AssociatedTable='C001'+substring(AssociatedTable,4,200); will not run as there is no scope for AssociatedTable to substring - the string needs to contain the name of the table completely to be able to be executed
Instead of
exec #qry;
You need
exec sp_executesql #qry;
You'll also need to change the type of #qry to NVARCHAR. Note that because of the dynamic sql, the proc is prone to SQL Injection and other escaping issues (i.e. ensure that #CompanyId is validated)
Is there a way I can convert a SQL Server 2008 Table to HTML table text, without knowing the structure of the table first?
I tried this:
USE [Altiris]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spCustomTable2HTML] (
#TABLENAME NVARCHAR(500),
#OUTPUT NVARCHAR(MAX) OUTPUT,
#TBL_STYLE NVARCHAR(1024) = '',
#HDR_STYLE NVARCHAR(1024) = '')
AS
-- #exec_str stores the dynamic SQL Query
-- #ParmDefinition stores the parameter definition for the dynamic SQL
DECLARE #exec_str NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
--We need to use Dynamic SQL at this point so we can expand the input table name parameter
SET #exec_str= N'
DECLARE #exec_str NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
--Make a copy of the original table adding an indexing columnWe need to add an index column to the table to facilitate sorting so we can maintain the
--original table order as we iterate through adding HTML tags to the table fields.
--New column called CustColHTML_ID (unlikely to be used by someone else!)
--
select CustColHTML_ID=0,* INTO #CustomTable2HTML FROM ' + #TABLENAME + '
--Now alter the table to add the auto-incrementing index. This will facilitate row finding
DECLARE #COUNTER INT
SET #COUNTER=0
UPDATE #CustomTable2HTML SET #COUNTER = CustColHTML_ID=#COUNTER+1
-- #HTMLROWS will store all the rows in HTML format
-- #ROW will store each HTML row as fields on each row are iterated through
-- using dymamic SQL and a cursor
-- #FIELDS will store the header row for the HTML Table
DECLARE #HTMLROWS NVARCHAR(MAX) DECLARE #FIELDS NVARCHAR(MAX)
SET #HTMLROWS='''' DECLARE #ROW NVARCHAR(MAX)
-- Create the first HTML row for the table (the table header). Ignore our indexing column!
SET #FIELDS=''<tr ' + #HDR_STYLE + '>''
SELECT #FIELDS=COALESCE(#FIELDS, '' '','''')+''<td>'' + name + ''</td>''
FROM tempdb.sys.Columns
WHERE object_id=object_id(''tempdb..#CustomTable2HTML'')
AND name not like ''CustColHTML_ID''
SET #FIELDS=#FIELDS + ''</tr>''
-- #ColumnName stores the column name as found by the table cursor
-- #maxrows is a count of the rows in the table, and #rownum is for marking the
-- ''current'' row whilst processing
DECLARE #ColumnName NVARCHAR(500)
DECLARE #maxrows INT
DECLARE #rownum INT
--Find row count of our temporary table
SELECT #maxrows=count(*) FROM #CustomTable2HTML
--Create a cursor which will look through all the column names specified in the temporary table
--but exclude the index column we added (CustColHTML_ID)
DECLARE col CURSOR FOR
SELECT name FROM tempdb.sys.Columns
WHERE object_id=object_id(''tempdb..#CustomTable2HTML'')
AND name not like ''CustColHTML_ID''
ORDER BY column_id ASC
--For each row, generate dymanic SQL which requests the each column name in turn by
--iterating through a cursor
SET #rowNum=0
SET #ParmDefinition=N''#ROWOUT NVARCHAR(MAX) OUTPUT,#rowNum_IN INT''
While #rowNum < #maxrows
BEGIN
SET #HTMLROWS=#HTMLROWS + ''<tr>''
SET #rowNum=#rowNum +1
OPEN col
FETCH NEXT FROM col INTO #ColumnName
WHILE ##FETCH_STATUS=0
BEGIN
--Get nth row from table
--SET #exec_str=''SELECT #ROWOUT=(select top 1 ['' + #ColumnName + ''] from (select top '' + cast(#rownum as varchar) + '' * from #CustomTable2HTML order by CustColHTML_ID ASC) xxx order by CustColHTML_ID DESC)''
SET #exec_str=''SELECT #ROWOUT=(select ['' + #ColumnName + ''] from #CustomTable2HTML where CustColHTML_ID=#rowNum_IN)''
EXEC sp_executesql
#exec_str,
#ParmDefinition,
#ROWOUT=#ROW OUTPUT,
#rowNum_IN=#rownum
SET #HTMLROWS =#HTMLROWS + ''<td>'' + #ROW + ''</td>''
FETCH NEXT FROM col INTO #ColumnName
END
CLOSE col
SET #HTMLROWS=#HTMLROWS + ''</tr>''
END
SET #OUTPUT=''''
IF #maxrows>0
SET #OUTPUT= ''<table ' + #TBL_STYLE + '>'' + #FIELDS + #HTMLROWS + ''</table>''
DEALLOCATE col
'
DECLARE #ParamDefinition nvarchar(max)
SET #ParamDefinition=N'#OUTPUT NVARCHAR(MAX) OUTPUT'
--Execute Dynamic SQL. HTML table is stored in #OUTPUT which is passed back up (as it's
--a parameter to this SP)
EXEC sp_executesql #exec_str,
#ParamDefinition,
#OUTPUT=#OUTPUT OUTPUT
RETURN 1
but when I execute the procedure
DECLARE #HTML NVARCHAR(MAX)
EXEC SpCustomTable2HTML 'Users', #HTML OUTPUT
SELECT #HTML
it keeps returning null.
Any ideas?
This SQL Fiddle DEMO shows your problem. When ALL the columns in ALL rows have values, you get a proper HTML table. When ANY NULLs exist, it turns the entire thing into NULL because
NULL + <any> = NULL
To fix it, simply change line 90 to handle nulls, i.e.
SET #HTMLROWS =#HTMLROWS + '''' + ISNULL(#ROW,'''') + ''''
The fixed SQL Fiddle DEMO
I realise it's been a while (to say the least) since this question was active but I thought I would post a few comments on this thread, as it turned up in a recent search.
Apologies if this (unintentionally) annoys the question asker but I believe the approach being used is both inefficient and difficult to understand - and therefore maintain.
There's no need to copy the database data before using it to generate the HTML table. It's just my humble opinion, but using dynamic SQL to generate dynamic SQL is also counter-intuitive.
Furthermore, database data values that contain HTML tags (or, worse still, malformed HTML tags) need to be escaped, so that they can be rendered correctly. For example, database data such as "value > 10" needs to generate the HTML "<td>value > 10</td>".
The following code addresses all of the above points, by using the built-in FOR XML clause:
CREATE PROCEDURE dbo.spCustomTable2HTML
#TABLENAME nvarchar(500),
#TBL_STYLE nvarchar(1024) = '',
#HDR_STYLE nvarchar(1024) = '',
#OUTPUT nvarchar(MAX) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
-- Declare variables
DECLARE #Columns nvarchar(MAX) = '',
#Data nvarchar(MAX),
#SQL nvarchar(MAX);
-- Snapshot columns (to force use of tempdb)
IF OBJECT_ID('tempdb.dbo.##spCustomTable2HTMLColumns') IS NOT NULL
BEGIN
DROP TABLE ##spCustomTable2HTMLColumns;
END
SET #SQL =
'SELECT TOP 0 *
INTO ##spCustomTable2HTMLColumns
FROM ' + #TABLENAME;
EXEC sp_executesql #SQL;
-- Build header row
SET #OUTPUT = (SELECT name AS td
FROM tempdb.sys.columns
WHERE object_id = OBJECT_ID('tempdb.dbo.##spCustomTable2HTMLColumns')
ORDER BY column_id
FOR XML RAW(''), ELEMENTS);
SET #OUTPUT += '</tr>'
-- Build column list
SELECT #Columns += '[' + name + '] AS td,'
FROM tempdb.sys.columns
WHERE object_id = OBJECT_ID('tempdb.dbo.##spCustomTable2HTMLColumns')
ORDER BY column_id;
SET #Columns = LEFT(#Columns, LEN(#Columns) - 1); -- Strip trailing comma
-- Delete columns snapshot
DROP TABLE ##spCustomTable2HTMLColumns;
-- Build data rows
SET #SQL =
'SET #Data = CONVERT(varchar(MAX),
(SELECT ' + #Columns +
' FROM ' + #TABLENAME +
' FOR XML RAW (''tr''), ELEMENTS XSINIL))';
EXEC sp_executesql #SQL, N'#Data NVARCHAR(MAX) OUTPUT', #Data = #Data OUTPUT;
SET #Data = REPLACE(#Data, ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"', ''); -- Remove XSI namespace
SET #Data = REPLACE(#Data, ' xsi:nil="true"', ''); -- Remove XSI attributes
SET #OUTPUT += #Data;
-- Prefix table/row headers
SET #OUTPUT = REPLACE(#OUTPUT, ' ', ' '); -- Use non-breaking spaces
SET #OUTPUT = REPLACE(#OUTPUT, '</tr>', '</tr>' + CHAR(13) + CHAR(10)); -- Add new line per row (to improve rendering in Microsoft Outlook)
SET #OUTPUT = '<table ' + #TBL_STYLE + '>' +
'<tr ' + #HDR_STYLE + '>' +
#OUTPUT +
'</table>';
END
In this stored procedure I want to get list of all the tables of a specific database when I give the database name as input.
For example when I call sp_list(master) it shows me the tables of the master database.
How can do this using sp_msforeachtable?
I found this code
sp_msforeachtable ' select ''?'' as ''Table'', count(*) as ''Rows'' from ? '
but cannot give database name in it as input
From this webpage:
declare #query as nvarchar(max)
declare #dbname as nvarchar(max)
SET #query=''
SET #dbname ='TST'
SET #query =#query + #dbname + '..sp_msforeachtable '' select ''''?'''' as ''''Table'''', count(*) as ''''Rows'''' from ? '''
EXEC sp_executesql #query