2012-03-26 15 views
0

テーブルに挿入するデータ(親から子へ、多対1の関係すべて):プログラム、モジュール、クラスおよびメンバー。各テーブルは、自動識別情報を主キーとして使用します。これは、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 

は、私が(モジュールなど、その後、第1のインサート番組表)、複数のストアドプロシージャにこれを破るために持っていますされ、またはよりシンプルで効率的な方法を持つことは可能でしょうか?

+0

これは特定のデータベース用ですか、ポータブルである必要がありますか? –

+0

SQL Server 2008だけの質問が更新されました。 – Icerman

答えて

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(Program <= Module <= Class <= Member)があります。 – Icerman

+0

これは良いですか? –

+0

私の良さ! Mergeですべてを考えました。今はCursorレッスンです。これは素晴らしいものです! – Icerman

関連する問題