2017-03-28 7 views
1

列名がa、b、c、d、e、fの表table1があります。 ここでは、各列の値を取得して1つの行の値にし、それを他のtable2 - columns(x、y、z)に挿入します。だから、私のクエリは次のようになります:列名を動的に追加し、その値を行sqlサーバーとして追加します。

insert into table2 (x, y, z) 
select a, '', '' from table1 
union all 
select b, '', '' from table1 
union all 
select c, '', '' from table1 
union all 
select d, '', '' from table1 
union all 
select e, '', '' from table1 
. 
. 
. 
union all 
select f, '', '' from table1 

新しいカラムがtable1に追加されたら、もう一度これにselect文を追加する必要があります。ちょうどこれを避けたいのですが、どのようにして自動的にすべての列を考慮してより短くする動的クエリを書くことができますか?

答えて

2

動的EAV構造(エンティティ属性値)を探しているようです。今クールの部分は@YourTable

Declare @YourTable table (ID int,Col1 varchar(25),Col2 varchar(25),Col3 varchar(25)) 
Insert Into @YourTable values 
(1,'a','z','k') 
,(2,'g','b','p') 
,(3,'k','d','a') 


Select A.ID 
     ,C.* 
From @YourTable A 
Cross Apply (Select XMLData=cast((Select A.* for XML Raw) as xml)) B 
Cross Apply (
       Select Attribute = attr.value('local-name(.)','varchar(100)') 
         ,Value  = attr.value('.','varchar(max)')    -- change datatype if necessary 
       From B.XMLData.nodes('/row') as A(r) 
       Cross Apply A.r.nodes('./@*') AS B(attr) 
       Where attr.value('local-name(.)','varchar(100)') not in ('ID','OtherFieldsToExclude') -- Field Names case sensitive 
      ) C 

戻り

ID  Attribute Value 
1  Col1  a 
1  Col2  z 
1  Col3  k 
2  Col1  g 
2  Col2  b 
2  Col3  p 
3  Col1  k 
3  Col2  d 
3  Col3  a 
+0

これは私の問題を解決しました。カラム名と値の両方が来ています。しかし、私はまだこの方法を理解することに頭を悩ましています。 –

+0

@AjayRawat Cross Applyは非常に強力なオプションです。最初の行は行をXMLに変換します。 2回目のクロス・アプライはそのXMLを取り、結果をアンピボットします。 –

1

これはcross applyを使用して行うための簡単な方法:

insert into table2 (x, y, z) 
    select v.x, '', '' 
    from table1 t1 cross apply 
     (values (t1.a), (t1.b), (t1.c), (t1.d), (t1.e), (t1.f) 
     ) v(x); 

新しい列がテーブルに追加されたときに新しい値を挿入したい場合、あなたはDDL、おそらくDMLトリガーをしたいと思います。 DMLトリガーは「標準」トリガーです。

documentationでDDLトリガーについて読むことができます。

つまり、新しい列と新しいテーブルを追加することを奨励するデータベースシステムは非常に疑わしいです。たとえば、属性の柔軟性を高めるEAVデータモデルを使用するなど、アプリケーションを設計する方がよいでしょう。

0

この

insert into table2 
select Tmp.id, tb1.* from table1 tb1, 
((SELECT B.id FROM (SELECT [value] = CONVERT(XML ,'<v>' + REPLACE('a,b,c,d,e,f' , ',' , '</v><v>')+ '</v>')) A  
OUTER APPLY 
(SELECT id = N.v.value('.' , 'varchar(100)') FROM A.[value].nodes('/v') N (v)) B)) Tmp 
0

これを試してみてください任意のクエリ可能性があり、私はそれを正しく読んでいた場合に最適な時間のように見えます PIVOTを使用してください。

関連する問題