[英]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.