web-dev-qa-db-ja.com

動的列を使用したCREATETABLE

一時テーブルにデータを挿入する必要があります。

いくつかの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 :(

7
Billa

ほのめかされているように、最善の策は、必要なすべての列を作成し、オプションの場合はそれらを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
1
Shock

動的列はいくつ必要ですか?

タイプnvarchar(MAX)などのDynamicという列を作成すると、データをそこに配置して、必要に応じてフォーマットできます。

もう1つのオプションは、NULL列のテーブルを作成することです。

SQLでこれを行うには、次のようにします。

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

上記のNULL列にも注意してください。

SQLでPrimary Keys列とNULL列を使用してテーブルを作成する方法の詳細については、こちらを参照してください。

SQLでテーブルを作成

1
rhughes

以下の例を参照してください。

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)
0
Suresh

以下のコードがあなたのために働くかもしれません。

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
0
Pratik Gohil

このテーブルが大きい場合は、ロジックでこのテーブルを使用してJOINSを作成し、TARGETTABLEでインデックスを作成する必要があると思います。

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
0
Valentin Petkov

あなたが本当に探しているものはSQLでは不可能だと思います。よくわかりませんが、たとえば、条件を満たすタプルの列を追加する必要があります。したがって、NoSQLのような他のデータベースエンジンが必要だと思います(私はNoSQLにあまり詳しくありませんが、水平方向に拡張できることを知っています)

SQLから切り替えたくない場合は、設計を再検討する必要があると思います。
デザインを主張する場合は、たとえば、列、名前「列名」、別の列「列データ」を追加し、必要に応じて入力するなどの操作を行うことができます。ただし、ご覧のとおり、「列データ」のデータは同じタイプである必要があるなど、独自の制約があります。

0
Shadi Hariri

これを試して。

 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 
 
 Id、DeptID、DeptName、Salary、Code Fromdbo.Employeeを選択します
ドロップテーブル#myTempTable 
終了
 
その他
 
開始
 
 CREATE TABLE# myTempTable2(Id INT、DeptId INT、DeptName VARCHAR(100))
 
 Insert Into #myTempTable(Id、DeptId、DeptName)
 Emp.Id、Emp.DeptID、Empを選択します.DeptName 
 From dbo.Employee As Emp 
 
 Select Id、DeptID、DeptName From dbo.Employee 
 
 Drop Table#myTempTable2 
    終わり[。__ __。] 
 
 
コミットトラン
0
user3605493

条件が満たされたときに一時テーブルを変更することもできます(この時点で必要な列を知っていると思いますか?)

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

他の人が指摘しているように、列をnull許容として事前に作成するか、条件が満たされた後にテーブルを作成することができます。

0
Stephen

使用できますか

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

以前に定義したプレースホルダー列の名前を変更するコマンド。
たとえば、#tempTable"VCHAR100_1""BOOL_1"などの追加フィールドを使用して"Int_1"を作成します。フィールドを使用する必要がある場合は、名前を変更します。後でコードが非暗号名で列を参照できるように、目的の名前に変更します。

0
MichaelSc

完全に動的な列を使用した別のソリューションを次に示します。

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に置き換えると、これは機能しません。それを修正して正しい列名リストを取得するには、範囲外のいくつかのトリックを使用できます。ただし、それでも非一時テーブルでは機能します。

0
Alex Peshik

コードを使用して、それが機能しているかどうかを教えてください??

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

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

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

私はそれがうまくいくことを願っています

0
Sandesh