您认为这可能是此模型的最佳方法
我们有一个邻接列表模型,如
CREATE TABLE ITEM (id varchar(10), name varchar(50), parent varchar(10))
具有以下要求:"项目的父项必须是最近的id"
的子字符串例如
id name parent
--------------------------
10 ItemA null
1000 ItemB 10
10005 ItemC 1000
此模型需要触发器来维护数据完整性
两个帮助功能
CREATE FUNCTION fxAntecesors(@id varchar(10))
RETURNS TABLE AS
RETURN (
SELECT * FROM ITEM
WHERE @id LIKE id + '%' AND @id <> id
)
CREATE FUNCTION fxParent (@id varchar(10))
RETURNS varchar(10) AS
BEGIN
DECLARE @parent varchar(10)
SELECT @padre = MAX(id) FROM fxAntecesors(@id)
RETURN @parent
END
OnInsert设置正确的父
CREATE TRIGGER OnItemInsert ON ITEM
FOR INSERT AS
UPDATE ITEM
SET ITEM.parent = INSERTED.código
FROM ITEM, INSERTED
WHERE fxParent(ITEM.id) = INSERTED.id
OnDelete指向父母
CREATE TRIGGER OnItemDelete ON ITEM
FOR DELETE AS
UPDATE ITEM
SET ITEM.parent = DELETED.parent
FROM ITEM, DELETED
WHERE ITEM.parent = DELETED.id
插入项目
CREATE PROCEDURE spItemInsert (@id varchar(10), @name varchar(50)) AS
INSERT INTO ITEM (id, name, parent) VALUES (@id, @name, fxParent(@id))
然后例如插入ItemD ...
EXEC spItemInsert('100', 'ItemD')
表格如下
id name parent
-------------------------
10 ItemA null
100 ItemD 10 /// New Item Inserted ///
1000 ItemB 100 /// Parent updated on insert ItemD ///
10005 ItemC 1000
我想知道是否有更好的模特?
关于这个问题,有哪些正式的规范?
感谢您的帮助,希望我能正确解释
但我认为通过这个解决方案,我们会遇到同样的问题,可能会更复杂
请注意,Funky_id与用户相关
CREATE FUNCTION fxAntecesors(@funkyid varchar(10))
RETURN TABLE AS
RETURN (SELECT * FROM ITEM_FUNKY_ID WHERE @funkyid LIKE funky_id + '%' AND @funkyid <> funky_id)
CREATE FUNCTION fxParentFunkyId (@funkyid varchar(10))
RETURNS varchar(10) AS
BEGIN
DECLARE @funkyparent varchar(10)
SELECT @funkyparent = MAX(funky_id) FROM fxAntecesors(@funkyid)
RETURN @funkyparent
END
CREATE FUNCTION fxParent(@funkyid varchar(10))
RETURN int
BEGIN
DECLARE @parent int
SELECT @parent = item_id FROM ITEM_FUNKY_ID WHERE funky_id = fxParentFunkyid(@funkyid)
RETURN @parent
END
CREATE FUNCTION fxFunkyId(@id int)
RETURN varchar(10)
BEGIN
DECLARE @funkyid varchar(10)
SELECT @funkyid = funky_id FROM ITEM_FUNKY_ID WHERE item_id = @id
RETURN @funkyid
END
CREATE PROCEDURE spItemInsert(@funkyid varchar(10), @name varchar(50)) AS
BEGIN
DECLARE @id int
SELECT @id = MAX(id) FROM ITEM
IF @id IS NULL
SET @id = 1
ELSE
SET @id = @id + 1
INSERT INTO ITEM (id, name, parent) VALUES (@id, @name, fxParent(@funkyid))
INSERT INTO ITEM_FUNKY_ID (item_id, funky_id) VALUES (@id, @funkyid)
END
CREATE TRIGGER OnInsertItemFunkyId ON ITEM_FUNKY_ID
FOR INSERT AS
UPDATE ITEM
SET ITEM.parent = INSERTED.item_id
FROM ITEM, INSERTED
WHERE fxParentFunkyId(fxFunkyId(ITEM.id)) = INSERTED.funky_id
CREATE TRIGGER OnItemDelete ON ITEM
FOR DELETE AS
UPDATE ITEM
SET ITEM.parent = DELETED.parent
FROM ITEM, DELETED
WHERE ITEM.parent = DELETED.id
在这种情况下
id name parent item_id funky_id
------------------------------------ -------------------------------
1 ItemA null 1 10
2 ItemB 1 2 1000
3 ItemC 2 3 10005
After insert new item…
exec spItemInsert '100', 'ItemD'
id name parent item_id funky_id
------------------------------------ -------------------------------
1 ItemA null 1 10
2 ItemB 4 -> //Updated on Trigger// 2 1000
3 ItemC 2 3 10005
4 ItemD 1 4 100
我认为两种解决方案之间没有太大区别,第二种解决方案看起来更复杂
答案 0 :(得分:0)
我发表了评论。
虽然您已经给出了一些要求(父级是子字符串),但不清楚为什么需要这样做。在典型的关系数据库设计中,除了表示关系之外,ID不用作语义结构。如果我有这个要求,我不会直接存储这些ID,而是存储在相关的表中。
我原来评论的要点是要理解“为什么?”。为什么要以这种方式设置ID。我能想到的唯一的事情是排序和一些其他组件的要求。在这两种情况下,我都会有其他设计建议。
但是,我会在评论中回答您的问题并解释“在相关表格中”的含义,以下是如何将此信息放在相关表格中的示例。
首先,你的表应该是这样的:
CREATE TABLE ITEM (id integer, name varchar(50), parent integer)
然后创建相关表格:
CREATE TABLE ITEM_FUNKY_ID (item_id integer, funky_id varchar(10))
在此表中,您为ITEM表中的每个ID添加一行。然后在第二列中添加varchar id。任何“修复”(例如,当您删除项目时)都将在此表中完成,并且只更改funky_id列。
还有一点 - 您将问题标记为mysql和sql-server。通常,这在SO上是不受欢迎的。请选择您的平台。