我有以下数据样本要插入到表格中(从父级到子级,所有多对一关系):程序,模块,类和成员。每个表使用自动标识作为主键。这适用于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
我是否必须将其分解为多个存储过程(首先插入Program表,然后插入Module等),或者可以使用更简单,更有效的方法?
答案 0 :(得分: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;
另见
编辑:我重写了整个答案,因为它不正确。