[英]CREATE TABLE with Dynamic Column
我需要将一些数据插入临时表。
我有一些基于条件的列,如Salary
, Code
。
如何为基于条件的列创建表? 我不想使用 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 :(
您需要多少个动态列?
如果有一个名为Dynamic
of type nvarchar(MAX)
之类的列,那么你可以将数据放在那里并根据需要进行格式化。
另一种选择是创建一个包含NULL
列的表。
要在SQL中执行此操作,您可以执行以下操作:
CREATE TABLE tblPerson
(
PersonId INT,
FirstName NVARCHAR(256),
LastName NVARCHAR(256) NULL,
PRIMARY KEY (PersonId)
)
请注意上面的NULL
列。
有关在SQL中使用Primary Keys
和NULL
列创建表的更多说明,请参见此处:
如上所述,您最好的选择是创建所需的所有列,并在可选时使其为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
见下面的例子:
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)
下面的代码可能适合您。
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
您可以在条件满足时更改临时表(我假设您知道此时所需的列?)
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
正如其他人所指出的那样,您可以将列预先创建为可为空的列 - 或者在满足条件后创建表。
你能用吗?
sp_RENAME 'TableName.[OldColumnName]' , '[NewColumnName]', 'COLUMN'
用于更改先前定义的占位符列的名称的命令。
例如,使用额外的字段创建#tempTable
,例如"VCHAR100_1"
, "BOOL_1"
, "Int_1"
等。如果您需要使用该字段,请将其重命名为所需的名称,以便稍后您的代码可以引用该列一个非神秘的名字。
我认为你真正想要的是SQL不可能的。 因为我想要添加列,例如符合条件的元组。 所以我认为你需要一些像NoSQL这样的其他数据库引擎(我对NoSQL不是很熟悉,但我知道它可以横向扩展)
如果你不想从sql切换我认为你应该重新考虑你的设计。
如果你坚持你的设计,你可以做一些事情,例如添加一个列,命名“列名”和另一列“列数据”,并在需要时填写它。 但是你可以看到它有自己的约束,比如“列数据”的数据应该是相同的类型。
使用代码并告诉我它是否正常工作?
-----------------------------------------------------
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
------------------------------------
我希望它能奏效
如果这个表是BIG,我认为你和你的逻辑你用这个表进行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
尝试这个。
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
这是另一个具有完全动态列的解决方案:
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,则这将不起作用。 要修复它并获得正确的列名列表,您可能会使用超出范围的一些技巧。 但它仍适用于非临时表。
您可以生成动态改变表结构的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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.