[英]How can I populate a parent and a child table from another table?
我有一个包含单词列表和相关wordForms的表。 表中的典型数据如下所示。 请注意,WordForms的某些列结束,例如,有些只是以最后一个wordform字结束
Id Word WordForms
1 abandon abandoned, abandoning, abandonment, abandons
2 abstract abstraction, abstractions, abstractly, abstracts, e.g.
这是源数据表的布局:
CREATE TABLE [dbo].[TempWords]
(
[Id] INT IDENTITY (1, 1) NOT NULL,
[Word] NVARCHAR (MAX) NOT NULL,
[WordForms] NVARCHAR (MAX) NULL,
)
我想用这些数据来填充两个表。 我知道使用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,
)
谁能给我一些关于如何做到这一点的提示?
首先,您可以创建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
然后,您可以使用下面的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
您可以将单词插入到第一个表中,而不是解析单词表单,并将它们插入到子表中,并链接到父表。
链接到父表可以通过连接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)
最终的SELECT
可以很容易地修改为INSERT INTO dbo.WordForms (...) SELECT ...
链接到dbo.Words
可以在这里获得,你可以通过加入word
列来看到。
在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]
在[dbo].[Words]
WordId Word
1 abandon
2 abstract
在[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.