【问题标题】:How to generate temp table columns and datatypes automatically via script如何通过脚本自动生成临时表列和数据类型
【发布时间】:2013-01-14 22:58:16
【问题描述】:

我经常在 SQL 中创建临时表,我正在寻找一种为表定义自动生成列名和数据类型的方法,这样我就不必每次都查看它们。

例如我运行:

SELECT CustomerID
  ClientID,
  FirstName
  LastName
INTO #Test
From dbo.Customer

首先使用我需要的适当列和数据设置临时表。一旦我完成了这一切,我就返回并取出 INTO 语句并写下以下内容:

CREATE TABLE #Test
(
...
...
);

我想找到一种从临时表的初始创建中自动生成列名和数据类型的方法。现在,由于我最初是插入到一个自动创建的临时表中,所以我使用这个:

EXEC tempdb..sp_help '#Test';

这为我提供了我需要的一切,而无需查看所有列数据类型,但我想知道是否有一种方法可以自动生成类似这样的列名。所以自动生成会生成:

CustomerID int,
ClientID int,
FirstName varchar(50),
LastName varchar(50)

这将允许我将其复制并粘贴到我的创建表语句中。

【问题讨论】:

    标签: sql sql-server sql-server-2008


    【解决方案1】:

    这可能会给你一个开始:

    DECLARE @viewname VARCHAR(50);
    SET @viewname ='tableorviewname';
    SELECT  c.name + ' '+ t.name + 
    case t.name  
    WHEN 'varchar' THEN '('+CAST(c.max_length AS VARCHAR(3) )+'),'
    ELSE ',' 
    end
    FROM sys.columns c
    INNER JOIN sys.types AS t ON c.system_type_id = t.system_type_id
    WHERE object_id = (SELECT object_id from sys.objects where name = @viewname)
    ORDER BY c.column_id
    

    编辑:临时表:

    临时表略有不同,例如,这在 sql 2008 中适用于名为 #tv_source 的临时表

    DECLARE @viewortablename VARCHAR(50);
    SET @viewortablename ='tempdb..#tv_source';
    SELECT  c.name + ' '+ t.name + 
    case t.name  
    WHEN 'varchar' THEN '('+CAST(c.max_length AS VARCHAR(3) )+'),'
    ELSE ',' 
    end
    FROM tempdb.sys.columns c
    INNER JOIN sys.types AS t ON c.system_type_id = t.system_type_id
    WHERE object_id =  object_id(@viewortablename)
    ORDER BY c.column_id
    

    注意:这给出了一个逗号分隔的列表,但没有尝试删除最后一个逗号,它只给出一个列表,您可能希望将其放在字符串上并进行操作等,然后用作动态 sql 或东西。不过,它应该让您开始做自己想做的事。

    对其他人的注意,sql 2000 不会正确显示长度,例如在 varchar(45) 上,它只会列出 varchar 部分,我没有尝试针对这个问题重新处理。

    【讨论】:

    • 由于某种原因,我在 sys.objects 中找不到我的临时表,所以它总是返回空白
    • 我为临时表添加了一个额外的示例,注意临时表名称的 object_id 差异 = 并且当执行此操作时,临时表当然必须存在。
    • 非常有用。我添加了一些额外的 when 子句,以便您可以设置正确的精度。 WHEN 'numeric' THEN '('+rtrim(CAST(c.max_length AS VARCHAR(3)))+','+rtrim(CAST(c.precision AS VARCHAR(3)))+'),'
    • @MichaelCarn-Bennett 这行得通,正如我当时指出的那样,这真的是为了作为一个起点,可以在您在此处描述的基础上进行构建。
    【解决方案2】:
    SELECT
    ', ['+ac.name+'] '+Type_Name(User_type_id)+
    CASE WHEN Type_Name(User_type_id) = 'Decimal' 
          THEN +'('+CONVERT(Varchar(4),ac.Precision)+','+CONVERT(Varchar(4),ac.Scale)+')' 
          WHEN Type_Name(User_type_id) IN 
                ('tinyint','smallint','int','real','money','float','numeric','smallmoney','DateTime') 
          THEN ''
          ELSE +'('+CONVERT(Varchar(4),ac.Max_Length)+')' 
    END AS TableColumn
    FROM Tempdb.sys.all_columns AS ac
          INNER JOIN Tempdb.Sys.SysObjects AS so
                ON so.ID = ac.Object_ID
    WHERE 1 = 1
    AND so.Name = '##YourTempTableGoesHere'
    

    【讨论】:

      【解决方案3】:

      ...我已经创建了一个函数,可以输出列和数据类型的列表,如果对象是表,那对你有用吗?

      CREATE FUNCTION [dbo].[fnDiscoverColumns]
      ( @PObjectName NVARCHAR(300) )
      
      RETURNS @Data TABLE ( ColumnList NVARCHAR(350) )
      
      AS
      BEGIN
      
      DECLARE @PObjectID TABLE  ( [object_id] INT )
      INSERT @PObjectID ( [object_id] )
      
      SELECT [object_id] FROM sys.objects AS O WHERE O.name = @PObjectName AND O.type = 'U'
      
      DECLARE @PObjectDetails TABLE ( [RowNo] INT,[ColumnName] NVARCHAR(300),[XType] INT,[DataType] NVARCHAR(100),[system_type_id] INT,[user_type_id] INT,[MaxLength] NVARCHAR(5),[Precision] INT,[Scale] INT,[ColumnList] NVARCHAR(300) )
      
      INSERT @PObjectDetails ( [RowNo],[ColumnName],[XType],[DataType],[system_type_id],[user_type_id],[MaxLength],[Precision],[Scale],[ColumnList] )
      
      SELECT DISTINCT
      ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS 'RowNo',
      C.name AS 'ColumnName',
      T.xtype AS 'XType',
      UPPER(T.name) AS 'DataType',
      C.system_type_id,
      C.user_type_id,
      CASE WHEN C.max_length < 0 THEN 'MAX' ELSE CAST(C.max_length AS VARCHAR) END AS 'MaxLength',
      C.precision AS 'Precision',
      C.scale AS 'Scale',
      CASE
      WHEN [XType] IN (34,35,36,40,48,52,56,58,59,60,61,62,98,99,104,122,127,189,240,241) THEN QUOTENAME(C.name) +'  '+ UPPER(T.name) +',' 
      WHEN [XType] IN (106,108) THEN QUOTENAME(C.name) +'  '+ UPPER(T.name) +'('+ CAST([Precision] AS VARCHAR) +','+ CAST(C.scale AS VARCHAR) +'),'
      WHEN [XType] IN (41,42,43,165,167,173,175,231,239) THEN QUOTENAME(C.name) +'  '+ UPPER(T.name) +'('+ CASE WHEN C.max_length < 0 THEN 'MAX'  WHEN C.max_length > 1 THEN CAST(C.max_length / 2 AS VARCHAR) ELSE CAST(C.max_length AS VARCHAR) END +'),' ELSE NULL END AS 'ColumnList'
      FROM sys.all_columns AS C
      JOIN systypes AS T ON C.system_type_id = T.xusertype
      WHERE C.object_id = (SELECT * FROM @PObjectID)  --373576369
      
      --Return column names and data types
      INSERT @Data
      SELECT 'CREATE TABLE #ColumnsList ('
      
      INSERT @Data
      SELECT 
      CASE WHEN C.RowNo = (SELECT MAX(RowNo) FROM @PObjectDetails) THEN LEFT(C.ColumnList, ABS(LEN(C.ColumnList + ',') - 2)) ELSE C.ColumnList END AS 'GeneratedColumns'     
      FROM @PObjectDetails AS C
      
      INSERT @Data
      SELECT ')'
      
      RETURN
      END
      GO
      

      一旦提交到数据库,像这样运行它:

      SELECT * FROM [dbo].[fnDiscoverColumns] ('ExecutionLogStorage') --name of table
      

      这应该会给你这样的输出:

      CREATE TABLE #ColumnsList (
      [LogEntryId]  BIGINT,
      [InstanceName]  NVARCHAR(38),
      [ReportID]  UNIQUEIDENTIFIER,
      [UserName]  NVARCHAR(260),
      [ExecutionId]  NVARCHAR(64),
      [RequestType]  TINYINT,
      [Format]  NVARCHAR(26),
      [Parameters]  NTEXT,
      [ReportAction]  TINYINT,
      [TimeStart]  DATETIME,
      [TimeEnd]  DATETIME,
      [TimeDataRetrieval]  INT,
      [TimeProcessing]  INT,
      [TimeRendering]  INT,
      [Source]  TINYINT,
      [Status]  NVARCHAR(40),
      [ByteCount]  BIGINT,
      [RowCount]  BIGINT,
      [AdditionalInfo]  XML
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-29
        • 2020-04-09
        • 2020-03-12
        • 1970-01-01
        • 1970-01-01
        • 2020-07-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多