2012-03-26 26 views
0

我有以下數據插入表(從父到子,所有多對一關係)的示例:程序,模塊,類和成員。每個表使用自動標識作爲主鍵。這是SQL Server 2008高效地插入多級別父子表

Program Module Class Member 
Program1 M1 C1 Func1 
Program1 M1 C1 Func2 
Program1 M1 C2 Func3 
Program1 M2 C3 Func4 
Program1 M2 C4 Func5 
Program2 M3 C5 Func6 
Program2 M3 C5 Func7 
Program2 M3 C6 Func8 
Program2 M4 C7 Func9 
Program2 M4 C7 Func10 
Program2 M4 C8 Func11 

我一定要打入多個存儲過程本(插入節目表,再模塊等),或者它可能有更簡單,更有效的方法?

+0

這是針對特定的數據庫,還是您要求它是便攜式的? – 2012-03-26 06:04:47

+0

更新後的問題,僅適用於SQL Server 2008. – Icerman 2012-03-26 06:30:03

回答

1

表定義:

CREATE TABLE Programs (
    ID INT NOT NULL PRIMARY KEY IDENTITY(1,1), 
    Name varchar(50) 
); 
CREATE TABLE Modules (
    ID INT NOT NULL PRIMARY KEY IDENTITY(1,1), 
    ProgramID INT, 
    Name varchar(50) 
); 
CREATE TABLE Classes (
    ID INT NOT NULL PRIMARY KEY IDENTITY(1,1), 
    ModuleID INT, 
    Name varchar(50) 
); 
CREATE TABLE Functions (
    ID INT NOT NULL PRIMARY KEY IDENTITY(1,1), 
    ClassID INT, 
    Name varchar(50) 
); 

類型定義:

CREATE TYPE ProgramTableType AS TABLE 
(
    Program varchar(50), 
    Module varchar(50), 
    Class varchar(50), 
    Func varchar(50) 
); 

程序定義:

CREATE PROCEDURE dbo.sp_insert_definitions 
    @NewRows ProgramTableType READONLY 
AS 
    SET NOCOUNT ON; 

    DECLARE cur_new CURSOR FOR 
     SELECT Program, Module, Class, Func 
     FROM @NewRows 
     ORDER BY Program, Module, Class, Func; 

    DECLARE 
     -- Cache variables 
     @ProgramID int, 
     @ProgramName varchar(50) = NULL, 
     @ModuleID int, 
     @ModuleName varchar(50) = NULL, 
     @ClassID int, 
     @ClassName varchar(50) = NULL, 
     -- Iteration variables 
     @Program varchar(50), 
     @Module varchar(50), 
     @Class varchar(50), 
     @Func varchar(50); 

    OPEN cur_new; 

    FETCH NEXT FROM cur_new 
    INTO @Program, @Module, @Class, @Func; 

    -- Loop trough the cursor 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     -- Get or create program 
     IF @ProgramName IS NULL OR @Program <> @ProgramName 
     BEGIN 
      IF NOT EXISTS (SELECT NULL FROM Programs WHERE Name = @Program) 
       INSERT INTO Programs (Name) 
       VALUES (@Program); 

      SELECT 
       @ProgramID = ID, 
       @ProgramName = Name, 
       @ModuleID = NULL, 
       @ModuleName = NULL, 
       @ClassID = NULL, 
       @ClassName = NULL 
      FROM Programs 
      WHERE Name = @Program; 
     END 

     -- Get or create module 
     IF @ModuleName IS NULL OR @Module <> @ModuleName 
     BEGIN 
      IF NOT EXISTS (SELECT NULL FROM Modules WHERE Name = @Module AND ProgramID = @ProgramID) 
       INSERT INTO Modules (ProgramID, Name) 
       VALUES (@ProgramID, @Module); 

      SELECT 
       @ModuleID = ID, 
       @ModuleName = Name, 
       @ClassID = NULL, 
       @ClassName = NULL 
      FROM Modules 
      WHERE Name = @Module 
      AND ProgramID = @ProgramID; 
     END; 

     -- Get or create class 
     IF @ClassName IS NULL OR @Class <> @ClassName 
     BEGIN 
      IF NOT EXISTS (SELECT NULL FROM Classes WHERE Name = @Class AND ModuleID = @ModuleID) 
       INSERT INTO Classes (ModuleID, Name) 
       VALUES (@ModuleID, @Class); 

      SELECT 
       @ClassID = ID, 
       @ClassName = Name 
      FROM Classes 
      WHERE Name = @Class 
      AND ModuleID = @ModuleID; 
     END; 

     -- Create function if it doesn't exists 
     IF NOT EXISTS (SELECT NULL FROM Functions WHERE Name = @Func AND ClassID = @ClassID) 
      INSERT INTO Functions (ClassID, Name) 
      VALUES (@ClassID, @Func); 

     FETCH NEXT FROM cur_new 
     INTO @Program, @Module, @Class, @Func; 
    END 

    CLOSE cur_new; 
    DEALLOCATE cur_new; 
GO 

實施例:

BEGIN TRAN; 
DECLARE @NewData AS ProgramTableType; 
INSERT INTO @NewData (Program, Module, Class, Func) 
VALUES ('Program1', 'M1', 'C1', 'Func1'), 
('Program1', 'M1', 'C1', 'Func2'), 
('Program1', 'M1', 'C2', 'Func3'), 
('Program1', 'M2', 'C3', 'Func4'), 
('Program1', 'M2', 'C4', 'Func5'), 
('Program2', 'M3', 'C5', 'Func6'), 
('Program2', 'M3', 'C5', 'Func7'), 
('Program2', 'M3', 'C6', 'Func8'), 
('Program2', 'M4', 'C7', 'Func9'), 
('Program2', 'M4', 'C7', 'Func10'), 
('Program2', 'M4', 'C8', 'Func11'); 
EXEC sp_insert_definitions @NewData; 
COMMIT TRAN; 

找回原來的輸入:

SELECT p.Name AS Program, m.Name AS Module, c.Name AS Class, f.Name AS [Function] 
FROM Functions f 
INNER JOIN Classes c ON c.ID = f.ClassID 
INNER JOIN Modules m ON m.ID = c.ModuleID 
INNER JOIN Programs p ON p.ID = m.ProgramID; 

編輯請參見:我重寫了全部答案,因爲它是不正確的。

+0

仍在消化這一點。我認爲這反映了與我所擁有的不同的模式。我沒有單獨的綁定表。相反,每個子表都有一個FK到父表的ID(程序<= Module <= Class <= Member)。 – Icerman 2012-03-26 16:15:34

+0

這是更好嗎? – 2012-03-26 23:20:58

+0

我的天啊!只是想到了Merge中的一切,現在是光標課。這是偉大的東西! – Icerman 2012-03-27 00:58:26