3

有没有一种方法可以将 SQL Server 2008 表转换为 HTML 表文本,而无需先了解表的结构?

我试过这个:

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

但是当我执行程序时

DECLARE @HTML NVARCHAR(MAX)

EXEC SpCustomTable2HTML 'Users', @HTML OUTPUT

SELECT @HTML

它不断返回null

有任何想法吗?

4

2 回答 2

2

这个SQL Fiddle DEMO显示了你的问题。当所有行中的所有列都有值时,您将获得一个正确的 HTML 表。当存在 ANY NULL时,它会将整个事物变为 NULL,因为

空 + <any>= 空

要修复它,只需将第 90 行更改为处理空值,即

SET @HTMLROWS =@HTMLROWS + '''' + ISNULL(@ROW,'''') + ''''

固定的SQL Fiddle DEMO

于 2013-04-26T09:29:57.397 回答
0

我意识到自从这个问题活跃以来已经有一段时间了(至少可以说),但我想我会在这个线程上发表一些评论,因为它出现在最近的搜索中。

如果这(无意)惹恼了提问者,我深表歉意,但我相信所使用的方法效率低下且难以理解 - 因此需要维护。

在使用它来生成 HTML 表之前,无需复制数据库数据。这只是我的拙见,但是使用动态 SQL 生成动态 SQL 也是违反直觉的。

此外,需要对包含 HTML 标记(或者更糟糕的是,格式错误的 HTML 标记)的数据库数据值进行转义,以便正确呈现它们。例如“value > 10”等数据库数据需要生成HTML“<td>value > 10</td>”。

以下代码通过使用内置 FOR XML 子句解决了上述所有问题:

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, ' ', '&nbsp;');                           -- 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
于 2015-06-25T09:16:24.773 回答