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

Sam*_*tar 4 sql-server

我有一个包含单词列表和相关wordForms的表.表中的典型数据如下所示.请注意,WordForms的某些列结束,例如,有些只是以最后一个wordform字结束

Id  Word       WordForms
1   abandon    abandoned, abandoning, abandonment, abandons    
2   abstract   abstraction, abstractions, abstractly, abstracts, e.g.
Run Code Online (Sandbox Code Playgroud)

这是源数据表的布局:

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

我想用这些数据来填充两个表.我知道使用SQL INSERT INTO,但我认为只能帮助我使用一个表.我想要做的是取第一个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,
)
Run Code Online (Sandbox Code Playgroud)

谁能给我一些关于如何做到这一点的提示?

San*_*esh 7

首先,您可以创建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
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用下面的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
Run Code Online (Sandbox Code Playgroud)

  • @marilou - 感谢更新.很高兴我可以帮忙. (2认同)

Iva*_*tin 5

您可以将单词插入到第一个表中,而不是解析单词表单,并将它们插入到子表中,并链接到父表.

链接到父表可以通过加入word列(我猜它是唯一的)或通过做一些MERGE + OUTPUT事情来获得一步SOURCE.ID(来自@words_csv)和INSERTED.ID.你喜欢什么方式.

解析也可以通过多种方式实现,请查看此示例(实际上我不建议使用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)
Run Code Online (Sandbox Code Playgroud)

通过加入列可以看到最终SELECT可以轻松修改为INSERT INTO dbo.WordForms (...) SELECT ... 链接到dbo.Words此处word.