使用动态列创建表

时间:2013-03-14 04:33:25

标签: sql sql-server sql-server-2008 azure-sql-database azure-storage

我需要将一些数据插入到临时表中。

我有一些 基于条件的列,例如SalaryCode

如何为基于条件的列创建表? 我不想使用 SELECT INTO #tempTable

以下是代码:

DECLARE @sql NVARCHAR(MAX)
,@sqlSelect NVARCHAR(MAX) = ''
,@sqlFrom NVARCHAR(MAX) =''

CREATE TABLE #myTempTable (Id INT, DeptId INT, DeptName VARCHAR(100))


SET @sqlSelect ='INSERT INTO #myTempTable
SELECT EMP.Id, EMP.DeptId, EMP.DeptName'

SET @sqlFrom =' FROM dbo.EMPLOYEE AS EMP'

IF (someCondition)
BEGIN
    SET @sqlSelect = @sqlSelect +', EMP.Salary, EMP.Code'            
END

SET @sql =  @sqlSelect +@sqlFrom 

EXEC sp_executesql @sql

关于我能做得更好的任何帮助/建议?


更新

最初我使用SELECT INTO #TempTable而没有指定列数,因为SQL Azure不支持,我决定使用INSERT INTO。但不确定如何在已定义的结构中添加动态列。它的完全动态SQL :(

12 个答案:

答案 0 :(得分:1)

您需要多少个动态列?

如果有一个名为Dynamic的{​​{1}}类型的列或类似内容,那么您可以将数据放在那里并根据需要进行格式化。

另一种选择是创建一个包含nvarchar(MAX)列的表。

要在SQL中执行此操作,您可以执行以下操作:

NULL

请注意上面的CREATE TABLE tblPerson ( PersonId INT, FirstName NVARCHAR(256), LastName NVARCHAR(256) NULL, PRIMARY KEY (PersonId) ) 列。

有关在SQL中创建包含NULLPrimary Keys列的表格的详细说明,请参阅此处:

Create tables in SQL

答案 1 :(得分:1)

如上所述,您最好的选择是创建所需的所有列,并在可选时将其设置为NULL。所以:

CREATE TABLE #myTempTable (Id INT, DeptId INT, DeptName VARCHAR(100), Salary INT NULL, EmpCode VARCHAR(45) NULL);

IF (someCondition)
BEGIN
    SET @sqlSelect = @sqlSelect +', EMP.Salary, EMP.Code'            
END
ELSE
BEGIN
    SET @sqlSelect = @sqlSelect +', NULL, NULL'            
END

答案 2 :(得分:0)

见下面的例子:

declare @sql nvarchar(400)
declare @ColFlag int
set @ColFlag = 1
if(@ColFlag = 0)

set  @sql= 'CREATE TABLE #myTempTable (Id INT, DeptId INT, DeptName VARCHAR(100)); 
    INSERT INTO #myTempTable SELECT 1,2,''DeptName1''; 
    SELECT * FROM #myTempTable'
else
set  @sql= 'CREATE TABLE #myTempTable (Id INT, DeptId INT, DeptName VARCHAR(100), MyNewColHere VARCHAR(25)); 
    INSERT INTO #myTempTable SELECT 1,2,''DeptName1'', ''MyNewColHereValue''; 
    SELECT * FROM #myTempTable'

 exec (@sql)

答案 3 :(得分:0)

以下代码可能适合您。

DECLARE @sql NVARCHAR(MAX)
,@sqlSelect NVARCHAR(MAX) = ''

,@sqlFrom NVARCHAR(MAX) =''

IF (someCondition)
BEGIN
    CREATE TABLE #myTempTable (Id INT, DeptId INT, DeptName VARCHAR(100))    
END
ELSE
BEGIN
    CREATE TABLE #myTempTable (Id INT, DeptId INT, DeptName VARCHAR(100),Salary numeric(18,2), Code INT)    
END

SET @sqlSelect ='INSERT INTO #myTempTable
SELECT EMP.Id, EMP.DeptId, EMP.DeptName'

SET @sqlFrom =' FROM dbo.EMPLOYEE AS EMP'

IF (someCondition)
BEGIN
    SET @sqlSelect = @sqlSelect +', EMP.Salary, EMP.Code'            
END

SET @sql =  @sqlSelect +@sqlFrom 

EXEC sp_executesql @sql

答案 4 :(得分:0)

您可以在满足条件时更改临时表(我假设您知道此时所需的列?)

IF (someCondition)
BEGIN
    ALTER TABLE #myTempTable ADD Salary VARCHAR(20), Code VARCHAR(20)
    SET @sqlSelect = @sqlSelect +', EMP.Salary, EMP.Code'            
END

如果您有多个可以激活的条件,您可能想先测试该列是否存在 - 您可以这样做:

IF COL_LENGTH('#myTemptable','Salary') IS NULL
BEGIN
     -- do something if salary doesn't exist
     ALTER TABLE #myTempTable ADD Salary NUMERIC(6,2)
END

正如其他人所说,您可以将列预先创建为可为空的列 - 或者在满足条件后创建表。

答案 5 :(得分:0)

可以使用

吗?
sp_RENAME 'TableName.[OldColumnName]' , '[NewColumnName]', 'COLUMN' 

命令用于更改先前定义的占位符列的名称 例如,使用#tempTable"VCHAR100_1""BOOL_1"等额外字段创建"Int_1"。如果您需要使用该字段,请将其重命名为所需名称,以便稍后您的代码可以通过非神秘的名称引用该列。

答案 6 :(得分:0)

我认为你真正想要的是SQL不可能。因为我想要添加列,例如符合条件的元组。所以我认为你需要一些像NoSQL这样的其他数据库引擎(我对NoSQL不是很熟悉,但我知道它可以横向扩展)

如果你不想从sql切换,我认为你应该重新考虑你的设计。
如果你坚持你的设计,你可以做一些事情,例如添加一个列,命名“列名”和另一列“列数据“并在需要时填写。但是你可以看到它有自己的约束,比如“列数据”的数据应该是相同的类型。

答案 7 :(得分:0)

使用代码并告诉我它是否正常工作?

-----------------------------------------------------

DECLARE @sql NVARCHAR(MAX)
,@sqlSelect NVARCHAR(MAX) = ''

,@sqlFrom NVARCHAR(MAX) =''

IF (someCondition)
BEGIN
    CREATE TABLE #tblInfo (Id INT, DeptId INT, DeptName VARCHAR(100))    
END
ELSE
BEGIN
    CREATE TABLE #tblInfo (Id INT, DeptId INT, DeptName VARCHAR(100),Salary numeric(18,2), Code INT)    
END

SET @sqlSelect ='INSERT INTO #tblInfo 
SELECT EMP.Id, EMP.DeptId, EMP.DeptName'

SET @sqlFrom =' FROM dbo.EMPLOYEE AS EMP'

IF (someCondition)
BEGIN
    SET @sqlSelect = @sqlSelect +', EMP.Salary, EMP.Code'            
END

SET @sql =  @sqlSelect +@sqlFrom 

EXEC sp_executesql @sql

------------------------------------

我希望它会起作用

答案 8 :(得分:0)

如果这个表很大,我认为你和你的逻辑你用这个表做JOINS你需要在TARGET TABLE中创建索引

你可以使用物理表而不是TEMP

DECLARE @guid NVARCHAR(64), @sql NVARCHAR(MAX)
,@sqlSelect NVARCHAR(MAX) = ''
,@sqlFrom NVARCHAR(MAX) ='', @sqlSchema NVARCHAR(MAX) =''

SET @guid = NEWID()  

declare @tableName NVARCHAR(64)= 'myTempTable'+ @guid

select @tableName

--use some transaction

set @sql = 'CREATE TABLE ' + @tableName  
set @sqlSchema = '(Id INT, DeptId INT, DeptName VARCHAR(100)'  -- DO INDEXES IF YOU ARE JOIN 

SET @sqlSelect ='INSERT INTO ' + @tableName +
'SELECT EMP.Id, EMP.DeptId, EMP.DeptName'


IF (1=1) -- your condition
BEGIN
  SET @sqlSchema = @sqlSchema +', EMP.Salary, EMP.Code'            
END

SET @sqlSchema =   @sqlSchema + ')' -- close last )

set @sql =  @sql +@sqlSchema --create the TargetTable


--DO YOUR logic

EXEC sp_executesql @sql

set @sql = N'DROP TABLE ' + @tableName

EXEC sp_executesql @sql

答案 9 :(得分:0)

试试这个。

Begin Tran


IF (someCondition)

    Begin 
      CREATE TABLE #myTempTable (Id INT, DeptId INT, DeptName VARCHAR(100), Salary money , Code Int)

        Insert Into #myTempTable(Id, DeptId, DeptName, Salary, Code)
        Select Emp.Id, Emp.DeptID, Emp.DeptName, EMP.Salary, EMP.Code 
        From dbo.Employee As Emp

        Select Id, DeptID, DeptName, Salary, Code From dbo.Employee
              Drop Table #myTempTable     
    End

    Else

    Begin

      CREATE TABLE #myTempTable2 (Id INT, DeptId INT, DeptName VARCHAR(100))

        Insert Into #myTempTable(Id, DeptId, DeptName)
        Select Emp.Id, Emp.DeptID, Emp.DeptName 
        From dbo.Employee As Emp

        Select Id, DeptID, DeptName From dbo.Employee

                    Drop Table #myTempTable2 
    End



Commit Tran

答案 10 :(得分:0)

以下是具有完全动态列的另一种解决方案:

DECLARE @sql NVARCHAR(MAX)
,@sqlTableName NVARCHAR(MAX) = ''
,@sqlColumnsDefinitions NVARCHAR(MAX) =''
,@sqlColumnsList NVARCHAR(MAX) =''
,@sqlFrom NVARCHAR(MAX) =''

SET @sqlTableName = 'myTempTable'
SET @sqlFrom = 'FROM dbo.EMPLOYEE AS EMP'

--conditions to define columns
IF (1=1)
    set @sqlColumnsDefinitions='Col1 int, Col2 int, Col3 int'
else
    set @sqlColumnsDefinitions='Col1 int, Col2 int, Col3 int, Col4 int, Col5 int'

--new table with dynamic fields creation
SET @sql = 'if (object_id('''+@sqlTableName+''') is not null) DROP TABLE '+@sqlTableName+'
CREATE TABLE '+@sqlTableName+' ('+@sqlColumnsDefinitions+')'+char(10)
print (@sql)
exec (@sql)

--get columns list
select @sqlColumnsList=STUFF((SELECT ',' + column_name
from INFORMATION_SCHEMA.COLUMNS where table_name like @sqlTableName+'%' FOR XML PATH('')), 1, 1, '')

--main insert
SET @sql = 'INSERT INTO '+@sqlTableName+char(10)+'SELECT '+@sqlColumnsList+char(10)+@sqlFrom
print (@sql)
exec  (@sql)

如果因为SQL引擎而将myTempTable替换为#myTempTable,则无效。要修复它并获得正确的列名列表,您可能会使用超出范围的一些技巧。但它仍适用于非临时表。

答案 11 :(得分:-1)

您可以生成动态改变表结构的ALTER语句。下面显示的是临时表,但当然这种方法也适用于普通表。

 IF OBJECT_ID( 'tempdb..#temp') IS NOT NULL
    BEGIN
   DROP TABLE #temp
   END
CREATE TABLE #temp
    (
    [CVRelID]       INT,
    [CustomerID]    INT,
    [VendorID]      INT,
    [TransactionID] INT
    )

DECLARE @script VARCHAR(8000)
SET     @script = 'ALTER TABLE #temp ADD '

SELECT  @script = @script + QUOTENAME(SDName) + ' VARCHAR(100),'
FROM    tblSupportDocuments
WHERE   SDIsActive = 1


SET     @script = SUBSTRING( @script, 1, LEN(@script) - 1)-- remove last ","
PRINT   @script
EXEC    (@script)