简体   繁体   English

使用动态列创建表

[英]CREATE TABLE with Dynamic Column

I need to insert some data into a temp table. 我需要将一些数据插入临时表。

I have some conditional based columns like Salary , Code . 我有一些基于条件的列,如SalaryCode

How can I create a table for conditional based columns? 如何为基于条件的列创建表? I don't want to use SELECT INTO #tempTable 我不想使用 SELECT INTO #tempTable

Here is the code: 这是代码:

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

Any help/suggestion on how better i can make this? 关于我能做得更好的任何帮助/建议?


Update: 更新:

Initially I used SELECT INTO #TempTable without specifying no of columns, As SQL Azure not supporting that, I decided to go with INSERT INTO . 最初我使用SELECT INTO #TempTable而没有指定任何列,因为SQL Azure不支持,我决定使用INSERT INTO But not sure how can I add dynamic columns in a defined structure already. 但不确定如何在已定义的结构中添加动态列。 Its fully dynamic SQL :( 它完全动态的SQL :(

How many dynamic columns do you need? 您需要多少个动态列?

What about having a column called Dynamic of type nvarchar(MAX) or something of the like, and then you can just put your data in there and format as appropriate. 如果有一个名为Dynamic of type nvarchar(MAX)之类的列,那么你可以将数据放在那里并根据需要进行格式化。

Another option is to create a table with NULL columns. 另一种选择是创建一个包含NULL列的表。

To do this in SQL, you can do the following: 要在SQL中执行此操作,您可以执行以下操作:

CREATE TABLE tblPerson
(
    PersonId INT,
    FirstName NVARCHAR(256),
    LastName NVARCHAR(256) NULL,
    PRIMARY KEY (PersonId)
)

Notice the NULL column above also. 请注意上面的NULL列。

See here for further explanation on creating tables with Primary Keys and NULL columns in SQL: 有关在SQL中使用Primary KeysNULL列创建表的更多说明,请参见此处:

Create tables in SQL 在SQL中创建表

As alluded to, your best bet is to likely create all of the columns that you will need and make them NULLable if optional. 如上所述,您最好的选择是创建所需的所有列,并在可选时使其为NULL。 So: 所以:

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

And

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

See example below: 见下面的例子:

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)

Below code may work for you. 下面的代码可能适合您。

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

You could just alter the temp table when the condition is met (I'm assuming you know the columns required at this point?) 您可以在条件满足时更改临时表(我假设您知道此时所需的列?)

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

You may want to test if the column exists first, if you have more than one condition that could be activated - which you can do like so: 如果您有多个可以激活的条件,您可能想要先测试该列是否存在 - 您可以这样做:

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

As others have noted, you could create the columns upfront as nullable - or create the table after the condition is met. 正如其他人所指出的那样,您可以将列预先创建为可为空的列 - 或者在满足条件后创建表。

Can you use the 你能用吗?

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

command to change the name of a previously defined place holder column. 用于更改先前定义的占位符列的名称的命令。
For example, create the #tempTable with extra fields such as "VCHAR100_1" , "BOOL_1" , "Int_1" , etc. If you need to use the field, rename it to the desired name so your code later on can refer to the column by a non-cryptic name. 例如,使用额外的字段创建#tempTable ,例如"VCHAR100_1""BOOL_1""Int_1"等。如果您需要使用该字段,请将其重命名为所需的名称,以便稍后您的代码可以引用该列一个非神秘的名字。

I think what you really are looking for is impossible for SQL. 我认为你真正想要的是SQL不可能的。 As I undrestand you want to add column for, for example tuples that met the conditions. 因为我想要添加列,例如符合条件的元组。 So I think you need some other database engines like NoSQL(I'm not very familiar with NoSQL but as much as I know it can horizontally scale) 所以我认为你需要一些像NoSQL这样的其他数据库引擎(我对NoSQL不是很熟悉,但我知道它可以横向扩展)

If you don't want to switch from sql I think you should reconsider your design. 如果你不想从sql切换我认为你应该重新考虑你的设计。
If you insist on your design you can do things like for example add a column, name "column name" and another column "column data" and fill it when its needed. 如果你坚持你的设计,你可以做一些事情,例如添加一个列,命名“列名”和另一列“列数据”,并在需要时填写它。 But as you can see it has its own constraints like the data of "column data" should be the same type. 但是你可以看到它有自己的约束,比如“列数据”的数据应该是相同的类型。

use the code and tell me is it working or not ?? 使用代码并告诉我它是否正常工作?

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

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

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

I hope it will work 我希望它能奏效

If this table is BIG I think your and in your logic you make JOINS with this table you need to create indexes in TARGET TABLE 如果这个表是BIG,我认为你和你的逻辑你用这个表进行JOINS你需要在TARGET TABLE中创建索引

You can go around with Physical table not TEMP 您可以使用物理表而不是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

Try This. 尝试这个。

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

Here is another solution with completely dynamic columns: 这是另一个具有完全动态列的解决方案:

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)

This won't work if you substite myTempTable with #myTempTable because of SQL engine. 如果因为SQL引擎而将myTempTable替换为#myTempTable,则这将不起作用。 To fix it and get correct column names list you may use some tricks that are out of scope. 要修复它并获得正确的列名列表,您可能会使用超出范围的一些技巧。 But still it works with non-temp tables. 但它仍适用于非临时表。

You can generate ALTER statements which dynamically alter the structure of your table. 您可以生成动态改变表结构的ALTER语句。 Shown below with a temp table, but of course the approach also works for normal tables. 下面显示的是临时表,但当然这种方法也适用于普通表。

 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM