SQL:从另一个表

时间:2017-10-11 16:36:33

标签: sql sql-server xml

我的问题有点不寻常。

我有一个包含3列(SQL Fiddle Link)的表:

ItemIdentifer  ItemClasses            RelevantItemDetails

Item1          Software              <xml document>
Item1          CRM                   <xml document>

现在,我需要做的是:

  1. 选择具有给定标识符的行。 (比如第1项)

  2. 为具有给定标识符的每个行构建一个临时表:这样Table_Name就是该行的ItemClass。 (所以,在这种情况下,我将有2个表 - 软件和CRM。)

  3. 转换RelevantItemDetails值=&gt;一个xml文本=&gt;进入相应表的表条目(我知道这个:))。

  4. 我已经学会了通过openxml页面https://docs.microsoft.com/en-us/sql/t-sql/functions/openxml-transact-sql执行第3步。我创建了一个sql过程,它从xml返回一个表。现在,我只需将其插入到我在步骤2中创建的临时表中(包含列名和值)。而且我迷失了。

    我怀疑1&amp; 2,我必须构建一个动态执行这些操作的过程。

    任何帮助都会非常有用。

    澄清:我没有得到两件事:

    1. 使用ItemClass名称作为表名动态构建表。 (所以,这里有Item1的2个表)。

    2. 该表的列和行由xml文档(即另一个表)定义。

    3.   

      所以,我只需要创建一个名称由ItemClass定义的表   由xml文档定义的列和行条目(假设我有一个   从xml创建的表,它也将动态生成,但我知道如何生成它。)

      我在这里动态创建表(T-SQL How to create tables dynamically in stored procedures?),但后来修复了这些列。在我的例子中,列是从另一个表派生的。而且我也必须插入值(再次,从列来自的相同表中派生)。

      编辑:示例行。

      ID  ItemName    ItemClass   Details
      10   WebApp     Software   <root><row ID="10" ItemName="WebApp" ItemDescription="desc" DisplayID="4962" /></root>
      

      编辑:样本决赛桌。

      TableName == Software
      
      ID  ItemName  ItemDescription  DisplayID 
      10  WebApp    "desc"            4962
      

3 个答案:

答案 0 :(得分:1)

以下代码段应该可以帮助您实现目标。

func datakontrol(){

let url = NSURL(string: "http://localhost.192.168.1.40.xip.io:8888/store1.php")
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in

    if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {

        guard let telefon = jsonObj!["telefon"] as? String else { return }
        GlobalVariables.telefonum = telefon
    }
}).resume()

答案 1 :(得分:1)

@items表类似于您当前的表格。然后是为每个ItemClass生成脚本的步骤。

DECLARE @n int,  -- counter
        @i int = 0, -- counter
        @tableName nvarchar(255), -- stores name of the current table
        @query nvarchar(4000)  -- stores a query that creates table

-- creates table like yours
DECLARE @items TABLE (
    ID int,
    ItemName nvarchar(100),
    ItemClass nvarchar(100),
    Details xml
)
-- put some data in a table
INSERT INTO @items VALUES
(10, N'WebApp', N'Software', N'<root><row ID="10" ItemName="WebApp" ItemDescription="desc" DisplayID="4962" /></root>'),
(12, N'WebApp', N'Software', N'<root><row ID="12" ItemName="WebApp" ItemDescription="desc" DisplayID="5687" /></root>'),
(11, N'CRMapp', N'CRM', N'<root><row ID="11" ItemName="CRMapp" ItemDescription="desc" DisplayID="823678" /></root>')

-- that table will store data for script generating
DECLARE @tables TABLE (
    ID int,
    TableName nvarchar(100),
    ColumnName sysname,
    ColumnValue nvarchar(max)
)
--here we parse XML to get column names and data
INSERT INTO @tables
SELECT  i.ID,
        i.ItemClass as TableName,
        CAST(t.c.query('local-name(.)') AS nvarchar(255)) AS ColumnName,
        t.c.value('.', 'nvarchar(max)') ColumnValue
FROM @items i
CROSS APPLY Details.nodes('//@*') as t(c)
-- count tables
SELECT @n = COUNT(DISTINCT TableName)
FROM @tables

-- here we go!
WHILE @n > @i
BEGIN
    -- select some table 
    SELECT TOP 1 @tableName = TableName
    FROM @tables
    -- in this CTE we get column names in order
    ;WITH tables_ AS (
        SELECT  ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID ) as rn,
                ColumnName
        FROM @tables
        WHERE TableName = @tableName    
    )


    -- here we build the create part
    SELECT @query = N'CREATE TABLE ' + QUOTENAME(@tableName) + '('
    +
    STUFF((
        SELECT N','+ QUOTENAME(ColumnName) +' nvarchar(max)'
        FROM tables_
        GROUP BY rn,ColumnName
        ORDER BY rn
        FOR XML PATH('')),1,1,'')
    +');
INSERT INTO ' + QUOTENAME(@tableName) +' VALUES'
    -- here comes data
    ;WITH cte AS (
        SELECT  ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID ) as rn,
                ID,
                ColumnValue
        FROM @tables
        WHERE TableName = @tableName
    )

    SELECT @query = @query + STUFF((
    SELECT ',('''+ [1] + ''',''' +[2] + ''',''' +[3] + ''',''' +[4]+''')'
    FROM cte
    PIVOT (max (ColumnValue) for rn in ([1],[2],[3],[4])) as bb
    FOR XML PATH('')),1,1,'');
    -- print query
    PRINT @query
    ---- execute query (first runt this script to print!)
    --EXEC (@query)

    SET @i+=1
    SET @query = N''

    DELETE FROM @tables
    WHERE TableName = @tableName
END

这将生成(并执行)脚本,如:

CREATE TABLE [Software]([ID] nvarchar(max),[ItemName] nvarchar(max),[ItemDescription] nvarchar(max),[DisplayID] nvarchar(max));
INSERT INTO [Software] VALUES('10','WebApp','desc','4962'),('12','WebApp','desc','5687')

CREATE TABLE [CRM]([ID] nvarchar(max),[ItemName] nvarchar(max),[ItemDescription] nvarchar(max),[DisplayID] nvarchar(max));
INSERT INTO [CRM] VALUES('11','CRMapp','desc','823678')

您可以添加检查表是否已存在。以及为表列获取正确数据类型的一些逻辑。也许XML中可以有超过4个属性。

答案 2 :(得分:0)

您可以使用EXECUTE(@script)函数并将任何类型的脚本作为字符串传递给它。喜欢:

EXECUTE('Create table my_table(id int)')

所以只需遍历查询并将所需的任何脚本传递给EXECUTE。