简体   繁体   English

如何从另一个表填充父表和子表?

[英]How can I populate a parent and a child table from another table?

I have a table containing a list of words and associated wordForms. 我有一个包含单词列表和相关wordForms的表。 The typical data in the table looks like this below. 表中的典型数据如下所示。 Note some of the columns of WordForms end in , eg and some just end with the last wordform word 请注意,WordForms的某些列结束,例如,有些只是以最后一个wordform字结束

Id  Word       WordForms
1   abandon    abandoned, abandoning, abandonment, abandons    
2   abstract   abstraction, abstractions, abstractly, abstracts, e.g.

Here is the layout of the source data table: 这是源数据表的布局:

CREATE TABLE [dbo].[TempWords]
(
    [Id]         INT            IDENTITY (1, 1) NOT NULL,
    [Word]       NVARCHAR (MAX) NOT NULL,
    [WordForms]  NVARCHAR (MAX) NULL,
)

I would like to use this data to populate two tables. 我想用这些数据来填充两个表。 I know about using SQL INSERT INTO but that will I think only help me with the one table. 我知道使用SQL INSERT INTO,但我认为只能帮助我使用一个表。 What I would like to do is to take the first Word, put that into the Words table and then separate the wordforms that are now divided up by a comma and put those into the WordForms Table. 我想要做的是取第一个Word,将其放入Words表中,然后将现在用逗号分隔的字形分开,并将它们放入WordForms表中。

CREATE TABLE [dbo].[Words]
(
    [WordId]     INT            IDENTITY (1, 1) NOT NULL,
    [Word]       NVARCHAR (MAX) NOT NULL
)

CREATE TABLE [dbo].[WordForms]
(
    [Id]         INT            IDENTITY (1, 1) NOT NULL,
    [WordId]     INT NOT NULL,
    [Text]  NVARCHAR (MAX) NULL,
)

Can anyone give me some tips as to how I can do this? 谁能给我一些关于如何做到这一点的提示?

First of all, you can create UDF function to separate CSV values. 首先,您可以创建UDF函数来分隔CSV值。

CREATE FUNCTION dbo.fn_Split (
      @InputString                  VARCHAR(8000),
      @Delimiter                    VARCHAR(50)
)

RETURNS @Items TABLE (
      Item                          VARCHAR(8000)
)

AS
BEGIN
      IF @Delimiter = ' '
      BEGIN
            SET @Delimiter = ','
            SET @InputString = REPLACE(@InputString, ' ', @Delimiter)
      END

      IF (@Delimiter IS NULL OR @Delimiter = '')
            SET @Delimiter = ','

--INSERT INTO @Items VALUES (@Delimiter) -- Diagnostic
--INSERT INTO @Items VALUES (@InputString) -- Diagnostic

      DECLARE @Item                 VARCHAR(8000)
      DECLARE @ItemList       VARCHAR(8000)
      DECLARE @DelimIndex     INT

      SET @ItemList = @InputString
      SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
      WHILE (@DelimIndex != 0)
      BEGIN
            SET @Item = SUBSTRING(@ItemList, 0, @DelimIndex)
            INSERT INTO @Items VALUES (@Item)

            -- Set @ItemList = @ItemList minus one less item
            SET @ItemList = SUBSTRING(@ItemList, @DelimIndex+1, LEN(@ItemList)-@DelimIndex)
            SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
      END -- End WHILE

      IF @Item IS NOT NULL -- At least one delimiter was encountered in @InputString
      BEGIN
            SET @Item = @ItemList
            INSERT INTO @Items VALUES (@Item)
      END

      -- No delimiters were encountered in @InputString, so just return @InputString
      ELSE INSERT INTO @Items VALUES (@InputString)

      RETURN

END -- End Function
GO

Then you can use below INSERT statements to populate tables. 然后,您可以使用下面的INSERT语句来填充表。

INSERT INTO [Words]
SELECT Word FROM TempWords


INSERT INTO WordForms

SELECT
    W.WordId,
    LTRIM(RTRIM(FNT.Item)) AS Item
FROM TempWords AS TW
INNER JOIN [Words] AS W
ON TW.[Word]=W.[Word]
CROSS APPLY fn_Split(REPLACE(TW.WordForms,', e.g.',''),',') AS FNT


SELECT * FROM [Words]
SELECT * FROM WordForms

You can insert words into first table, than parse word forms and insert them into child table with link to parent table. 您可以将单词插入到第一个表中,而不是解析单词表单,并将它们插入到子表中,并链接到父表。

Link to parent table can be obtained by joining on word column (I guess it's unique) or by doing some MERGE + OUTPUT thing to obtain in one step SOURCE.ID (from @words_csv) and INSERTED.ID . 链接到父表可以通过连接word列(我猜它是唯一的)或通过做一些MERGE + OUTPUT事来获得一步SOURCE.ID (来自@words_csv)和INSERTED.ID Any way you like. 你喜欢什么方式。

Parsing could be implemented in many ways too, check this example (actually I would not recommend to parse with sql at all). 解析也可以通过多种方式实现,请查看此示例(实际上我不建议使用sql进行解析 )。

DECLARE @words_csv TABLE (Id INT IDENTITY(1, 1), Word VARCHAR(100), WordForms VARCHAR(1000))

INSERT INTO @words_csv(word, wordforms)
VALUES
    ('abandon', 'abandoned, abandoning, abandonment, abandons, e.g.'),
    ('abstract', 'abstraction, abstractions, abstractly, abstracts')

--INSERT INTO [dbo].[Words](word)
--SELECT w.word
--FROM @words_csv w

;WITH word_forms_extracted AS
    (
        SELECT  w.id,
                w.word,
                ltrim(rtrim(cast(case when CHARINDEX(',', w.WordForms) > 0 then substring(w.wordforms, 1, CHARINDEX(',', w.WordForms)-1) end AS VARCHAR(1000)))) wordform,
                stuff(w.wordforms, 1, CHARINDEX(',', w.WordForms), '') wordforms
        FROM    @words_csv w

        UNION ALL

        SELECT  w.id,
                w.word,
                ltrim(rtrim(cast(case when CHARINDEX(',', wfe.WordForms) > 0 then substring(wfe.wordforms, 1, CHARINDEX(',', wfe.WordForms)-1) else wfe.wordforms end AS VARCHAR(1000)))) wordform,
                case when CHARINDEX(',', wfe.WordForms) > 0 then stuff(wfe.wordforms, 1, CHARINDEX(',', wfe.WordForms), '') ELSE '' end wordforms
        FROM    @words_csv w   
                INNER JOIN  word_forms_extracted wfe
                    ON  wfe.id = w.id
        WHERE wfe.wordforms != ''
    )
SELECT wf.id, wf.word, wf.wordform
FROM word_forms_extracted wf
--INNER JOIN [dbo].[Words] w
--ON w.word = wf.word
WHERE wf.wordform NOT IN ('', 'e.g.')
ORDER BY wf.id, wf.wordform
OPTION(MAXRECURSION 1000)

Final SELECT can be easily modified to INSERT INTO dbo.WordForms (...) SELECT ... Link to dbo.Words is obtained here as you can see by joining on word column. 最终的SELECT可以很容易地修改为INSERT INTO dbo.WordForms (...) SELECT ...链接到dbo.Words可以在这里获得,你可以通过加入word列来看到。

With the help of XML: 在XML的帮助下:

INSERT INTO [dbo].[Words]
SELECT DISTINCT [Word]
FROM [dbo].[TempWords] 

DECLARE @xml xml

SELECT @xml = (
    SELECT CAST('<row><word>'+WORD+'</word><w>' + REPLACE(WordForms,', ','</w><w>') +'</w></row>' as xml)
    FROM [dbo].[TempWords] 
    FOR XML PATH('')
    )


INSERT INTO [dbo].[WordForms]
SELECT  w.[WordId],
        t.v.value('.','nvarchar(max)') as [Text]
FROM @xml.nodes('/row/w') as t(v)
LEFT JOIN [dbo].[Words] w 
    ON t.v.value('../word[1]','nvarchar(max)')  = w.[Word]

In [dbo].[Words] [dbo].[Words]

WordId  Word
1       abandon
2       abstract

In [dbo].[WordForms] [dbo].[WordForms]

Id  WordId  Text
1   1       abandoned
2   1       abandoning
3   1       abandonment
4   1       abandons
5   2       abstraction
6   2       abstractions
7   2       abstractly
8   2       abstracts

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

相关问题 如何使用SQL使用来自父级的值填充子表? - How can I use SQL to populate a child table with a value from the parent? 如何通过查找每一行来填充另一个表格? - How can I populate a table from another with a look up for each row? 如何将数据从父列的一列移动到新的子表中? - How can I move data from one column of a parent into a new child table? 我如何使用LINQ从父/子表中获得数据的“固定”输出 - How can I get a “flat” output of data from a parent / child table with LINQ 事件源SQL填充父子表 - Event Sourcing SQL Populate Parent and Child Table 我如何基于一个视图中的某些值来计入父表中的所有记录和子表中的特定记录 - how can i tak all record from parent table and specific record from child table based on some values in one view 如何用其他表中的列表填充列? - How to populate column with list from another table? 当父子关系存储在同一个表中时,如何将父子关系值获取到新表中 - How can i get Parent-Child relationship values to new table when Parent and Child are stored in same table 如何从父子表获取结果 - How to get result from parent child table 如何创建触发器以从另一个数据库中的另一个表填充一个表 - How to create a trigger to populate a table from another table in a different database
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM