Ms-Access

將一張表上的 1 條記錄拆分為另一張表上的兩條記錄

  • January 19, 2022

我對此真的很陌生,所以請原諒我的無知,但我真的需要一些幫助!

我有兩個表:BillsFiled 和 Authors

在 BillsFiled 上,有以下列:ID、符號、文件日期、類型、作者、標題、摘要等

這是從導入的 Excel 文件中填充的,該文件由不關心我的引用完整性需求的外部源填充,這意味著“作者”欄位可以包含多個條目,例如:

ID-Symbol-------Filedate------Type------------Author--------------------Title--------------------Summary

1  -   s001  ----  11/18/2014  --- Resolution -- Smith ; Stevens   -----     A Resolution to... ------- yadayada

2  -   h002   ---- 11/18/2014 ---  Bill   -----------     Diaz       --------------------            A Bill to...    -----------------    yadayada

3   -  s002  ----  11/18/2014  ---- Bill    ---------    Ryan ; Smith ; Harris--  A bill...    --------------------       yadayada

因為我需要將“作者”連結到“符號”的記錄,所以我也有一個表:作者。這僅包含列:符號和作者。

我最熱切的希望是執行查詢或一些 vba 或宏或其他東西來拆分“BillFiled”中的多個條目以附加“作者”,例如:

Symbol   -     Author

s001          Smith

s001          Stevens

h002          Diaz

s002          Ryan

s002          Smith

s002          Harris

我在這個網站上找到了大約一年前提供的一串程式碼,以回應另一個使用者的一個非常相似的問題,並嘗試使用它,但得到了奇怪的結果。程式碼(用我的表名和列名更新)是:

Sub SplitIt()

Dim rstBillFiled As Recordset
Dim rstAuthors As Recordset
Dim Items() As String

' use dbOpenSnapshot to open the source table READ-ONLY
Set rstBillFiled = CurrentDb.OpenRecordset( _
       "SELECT Symbol, Author FROM BillFiled;" _
       , dbOpenSnapshot)
' use dbOpenDynaset to open the destination table READ-WRITE
Set rstAuthors = CurrentDb.OpenRecordset( _
       "SELECT Symbol, Author FROM BillFiled;" _
       , dbOpenDynaset)

With rstBillFiled
   ' .BOF is Beginning of the table
   ' .EOF is End of the table
   ' Checking if both are false means there are records in the
   ' source table
   If Not (.BOF And .EOF) Then
       ' get the first record from the source table
       .MoveFirst
       Do
           ' if Author is NULL (empty)
           If Nz(!Author, "") = "" Then
                   ' add a new record into the destination table
                   ' with data from the source table for Symbol
                   rstAuthors.AddNew
                   rstAuthors!Symbol = rstBillFiled!Symbol
                   ' set Author to NULL (empty)
                   rstAuthors!Author = Null
                   ' save the new record
                   rstAuthors.Update
           Else ' if Author IS NOT NULL
               ' convert Author into an array of strings
               Items = Split(Nz(!Author, ""), ";")
               ' loop through the array of strings
               For a = LBound(Items) To UBound(Items)
                   rstAuthors.AddNew
                   rstAuthors!Symbol = rstBillFiled!Symbol
                   ' Author is set to the current item in the array
                   rstAuthors!Author = Items(a)
                   rstAuthors.Update
               Next a
           End If
           ' load the next record from the source table
           .MoveNext
       ' repeat until the end of the source table is reached
       Loop Until .EOF
   End If
   ' close the source table
   rstBillFiled.Close
End With
' close the destination table
rstAuthors.Close

End Sub

使用從立即視窗執行 SplitIt 的指令。

當我這樣做時,它會收集和拆分記錄,但所有記錄都被添加到“BillFiled”而不是“Authors”中

它還對前兩條記錄重複該操作,這樣如果源表中共有 4 條記錄可歸屬於 6 位作者,它將向源表添加 8 條新記錄,而對目標表則不添加任何記錄。

正如我一開始所說,我真的不知道自己在做什麼,也沒有任何程式碼經驗,但我正在嘗試建立這個數據庫來幫助沒有時間的家庭成員開展業務學習如何。我有一些時間,但遺憾的是我不知道,所以如果有人能同情我,並用你經驗豐富的眼睛來看待這件事,我將不勝感激!謝謝!

看看這是否有效。

CREATE FUNCTION [dbo].[FN_CommaSeparator] (@array VARCHAR(max))

> RETURNS @Table TABLE (value VARCHAR(max))

AS
BEGIN
   DECLARE @separator_position INT
       ,@array_value VARCHAR(max)

   SET @array = @array + ','

   WHILE PATINDEX('%,%', @array) <> 0
   BEGIN
       SELECT @separator_position = PATINDEX('%,%', @array)

       SELECT @array_value = LEFT(@array, @separator_position - 1)

       INSERT @Table
       VALUES (@array_value)

       SELECT @array = STUFF(@array, 1, @separator_position, '')
   END

   RETURN
END

CREATE TABLE #Temp (
   Id VARCHAR(10)
   ,Author VARCHAR(50)
   )

CREATE TABLE #Temp2 (
   Id VARCHAR(10)
   ,Author VARCHAR(50)
   )

INSERT INTO dbo.#Temp (
   Id
   ,Author
   )
VALUES (
   'S1'
   ,'ABC,BCD'
   )
   ,(
   'S2'
   ,'CDE,DEF'
   )
   ,(
   'S3'
   ,'EFG,FGH'
   )
   ,(
   'S4'
   ,'GHI,HIJ'
   )

DECLARE @Id VARCHAR(50)
   ,@Author VARCHAR(50)

DECLARE ABC CURSOR
FOR
SELECT Id
   ,Author
FROM dbo.#Temp t

OPEN ABC

FETCH NEXT
FROM ABC
INTO @Id
   ,@Author

WHILE @@FETCH_STATUS = 0
BEGIN
   INSERT INTO dbo.#Temp2 (
       Id
       ,Author
       )
   SELECT @Id
       ,Value
   FROM dbo.FN_CommaSeparator(@Author)

   FETCH NEXT
   FROM ABC
   INTO @Id
       ,@Author
END

DEALLOCATE ABC

SELECT *
FROM dbo.#Temp2 t

DROP TABLE dbo.#Temp

DROP TABLE dbo.#Temp2

我遇到了類似的問題,並使用Pinal Dave的這種方法對其進行了整理:

CREATE TABLE #AuthorsList (ID INT, Author VARCHAR(50), Title VARCHAR(50))

INSERT INTO #AuthorsList (ID, Author, Title) VALUES (1,'Smith;Stevens','A Resolution to');
INSERT INTO #AuthorsList (ID, Author, Title) VALUES (2,'Diaz','A Bill to');
INSERT INTO #AuthorsList (ID, Author, Title) VALUES (3,'Ryan;Smith;Harris','A Something');

SELECT 
   ID,
   LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS Authors,
   Title
FROM
(
   SELECT 
       ID,
       CAST('<XMLRoot><RowData>' + REPLACE(Author,';','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x,
       Title
   FROM   
       #AuthorsList
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)

結果:

ID  Authors Title
------------------------------
1   Smith   A Resolution to
1   Stevens A Resolution to
2   Diaz    A Bill to
3   Ryan    A Something
3   Smith   A Something
3   Harris  A Something

引用自:https://dba.stackexchange.com/questions/86018