简体   繁体   English

T-SQL 查询将数据插入到具有可变列数的表中

[英]T-SQL query to insert data into a table with a variable number of columns

I am trying to insert data from the table A, assuming the data is ordering in the way it looks, into the table B.我正在尝试将表 A 中的数据插入表 B 中,假设数据按其外观排序。

The way the data should be loaded into table B is by id_column.数据应该加载到表 B 的方式是通过 id_column。 For example, the data which has id_column 1 has to be loaded into column C01.例如,具有 id_column 1 的数据必须加载到 C01 列。 Note that not all the data has the same number of column_id like int the case of the BLOCK 1 or BLOCK 3.请注意,并非所有数据都具有与 BLOCK 1 或 BLOCK 3 的 int 相同数量的 column_id。

The problem i am having is that the table B not always has the same amount of columns.我遇到的问题是表 B 并不总是具有相同数量的列。 In this case, it has 4 columns, but it could be 5 or more or less, so what i am trying is something that allow me the chance of work with different number of columns.在这种情况下,它有 4 列,但它可能是 5 或更多或更少,所以我正在尝试的是让我有机会使用不同数量的列。

(When i have created previously table B, i did it thinking in the maximum id_column of table A) (当我之前创建了表 B 时,我在考虑表 A 的最大 id_column 时这样做了)

图片

Please, some kind of suggestion?请问,有什么建议吗?

SQL tables represent unordered sets. SQL 表表示无序集。 Your ordering assumes an ordering in table A, so let me assume that you have such a column.您的排序假定表 A 中的排序,所以让我假设您有这样的列。

You can assign a grouping and then use conditional aggregation:您可以分配一个分组,然后使用条件聚合:

select max(case when column_id = 1 then value end) as c01,
       max(case when column_id = 2 then value end) as c02,
       max(case when column_id = 3 then value end) as c03,
       max(case when column_id = 4 then value end) as c04,
       'X' as con
from (select a.*,
             sum(case when column_id = 1 then 1 else 0 end) over (order by <ordering col>) as grp
      from a
     ) a
group by grp;

This assigns the groups by looking for column_id = 1 , which seems to indicate the start of a new block.这通过查找column_id = 1来分配组,这似乎表明新块的开始。

An INSERT statement can't handle a dynamic set of columns. INSERT 语句无法处理一组动态列。 You have to specify which columns your inserting into which means you have to SELECT a specific set of columns and in the same order that insert is in.您必须指定插入哪些列,这意味着您必须 SELECT 一组特定的列,并且与插入的顺序相同。

Having a table A like the one you have is a popular approach for dynamically created datasets and having a table like it is usually the end of of that data in the database.拥有像您所拥有的那样的表 A 是动态创建数据集的一种流行方法,并且拥有像这样的表通常是数据库中该数据的结尾。 Instead of trying to interpret that data any other way in your database (like storing it in your table B as well), most applications just select from the table A and then parse the data out into your objects in code.大多数应用程序没有尝试以任何其他方式在数据库中解释该数据(例如也将其存储在表 B 中),而是仅从表 A 中获取 select,然后将数据解析为代码中的对象。

Another option I like to do for datasets that have unknown columns is to stored the unknown parts in an xml column and then have column for the stuff you do know.对于具有未知列的数据集,我喜欢做的另一个选择是将未知部分存储在 xml 列中,然后为您知道的内容添加列。

An example would be一个例子是

CREATE TABLE tblData
(
   BlockID int NOT NULL PRIMARY KEY,
   Data xml
)

Then in code you will build the xml block with all the random columns.然后在代码中,您将使用所有随机列构建 xml 块。 And then parse it back out again in code.然后在代码中再次解析它。 This gives you the flexibility of the unknown.这为您提供了未知的灵活性。 Especially if some of those unknown columns might have additional meta data that you don't care to keep for other unknown columns.特别是如果其中一些未知列可能包含您不想为其他未知列保留的其他元数据。

Unfortunately, your only option is to do something using dynamic SQL.不幸的是,您唯一的选择是使用动态 SQL 做某事。 Here is some example code to do perform a dynamic pivot.这是一些执行动态 pivot 的示例代码。

CREATE TABLE #tblA
(
    BLK VARCHAR(100)
    ,COLUMN_ID INT
    ,VALUE VARCHAR(100)
)

INSERT INTO #tblA
(
    BLK
    ,COLUMN_ID
    ,VALUE
)
VALUES
('BLOCK 1', 1, 'AA')
,('BLOCK 1', 2, 'BB')
,('BLOCK 1', 3, 'CC')
,('BLOCK 2', 1, 'AAAA')
,('BLOCK 2', 2, 'BBBB')
,('BLOCK 2', 3, 'CCCC')
,('BLOCK 2', 4, 'DDDD')
,('BLOCK 3', 1, 'AAAAAA')
,('BLOCK 3', 2, 'BBBBBB')
,('BLOCK 3', 3, 'CCCCCC')
,('BLOCK 4', 1, 'AAAAAAAA')
,('BLOCK 4', 2, 'BBBBBBBB')
,('BLOCK 4', 3, 'CCCCCCCC')
,('BLOCK 4', 4, 'DDDDDDDD')

--END DEMO SETUP

DECLARE @sql NVARCHAR(MAX) = N'';
DECLARE @cols NVARCHAR(MAX) = N''

--BUILD LIST OF COLUMNS TO PIVOT
SELECT @cols += ',' + QUOTENAME('CO' + CAST(COLUMN_ID AS VARCHAR(10))) FROM #tblA GROUP BY COLUMN_ID
SELECT @cols = STUFF(@cols, 1,1,'')
--SELECT @cols

SELECT @sql = 'SELECT BLK, ' + @cols
    + ' FROM (' 
    + ' SELECT BLK, ''CO'' + CAST(COLUMN_ID AS VARCHAR(10)) AS ColName, Value FROM #tblA'
    + ') data'
    + ' PIVOT('
    + ' MAX(VALUE)'
    + ' FOR ColName IN  (' + @cols + ')'
    + ') AS pvt'
PRINT @sql
EXEC(@sql)

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

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