2012-05-01 22 views
1

问题:

有没有办法让外部ID指向比一个特定的表更通用的东西?在MySQL中,如何创建全局/通用外部ID?

详情:

我经常遇到在那里我有没有关系相互几个表的情况,但仍需要一个共同的表(在下面的例子发动机innodb

CREATE TABLE IF NOT EXISTS movies 
(
    id INT NOT NULL auto_increment, 
    name VARCHAR(100) NOT NULL , 

    PRIMARY KEY(id) 
); 

CREATE TABLE IF NOT EXISTS books 
(
    id INT NOT NULL auto_increment, 
    name VARCHAR(100) NOT NULL , 

    PRIMARY KEY(id) 
); 

CREATE TABLE IF NOT EXISTS songs 
(
    id INT NOT NULL auto_increment, 
    name VARCHAR(100) NOT NULL , 

    PRIMARY KEY(id) 
); 

CREATE TABLE IF NOT EXISTS news_papers 
(
    id INT NOT NULL auto_increment, 
    name VARCHAR(100) NOT NULL , 

    PRIMARY KEY(id) 
); 

CREATE TABLE IF NOT EXISTS scrolls 
(
    id INT NOT NULL auto_increment, 
    name VARCHAR(100) NOT NULL , 

    PRIMARY KEY(id) 
); 

CREATE TABLE IF NOT EXISTS sumarian_wheat_tablets 
(
    id INT NOT NULL auto_increment, 
    name VARCHAR(100) NOT NULL , 

    PRIMARY KEY(id) 
); 

现在我想保持的每每次记录,像这样

CREATE TABLE IF NOT EXISTS movie_history 
(
    id   INT NOT NULL auto_increment, 
    foreign_id INT NOT NULL , 
    view_date TIMESTAMP DEFAULT now(), 

    FOREIGN KEY (foreign_id) REFERENCES movies (id), 
    PRIMARY KEY(id) 
); 

CREATE TABLE IF NOT EXISTS book_history 
(
    id   INT NOT NULL auto_increment, 
    foreign_id INT NOT NULL , 
    view_date TIMESTAMP DEFAULT now(), 

    FOREIGN KEY (foreign_id) REFERENCES books (id), 
    PRIMARY KEY(id) 
); 

CREATE TABLE IF NOT EXISTS song_history 
(
    id   INT NOT NULL auto_increment, 
    foreign_id INT NOT NULL , 
    view_date TIMESTAMP DEFAULT now(), 

    FOREIGN KEY (foreign_id) REFERENCES songs (id), 
    PRIMARY KEY(id) 
); 

CREATE TABLE IF NOT EXISTS news_paper_history 
(
    id   INT NOT NULL auto_increment, 
    foreign_id INT NOT NULL , 
    view_date TIMESTAMP DEFAULT now(), 

    FOREIGN KEY (foreign_id) REFERENCES news_papers (id), 
    PRIMARY KEY(id) 
); 

CREATE TABLE IF NOT EXISTS scroll_history 
(
    id   INT NOT NULL auto_increment, 
    foreign_id INT NOT NULL , 
    view_date TIMESTAMP DEFAULT now(), 

    FOREIGN KEY (foreign_id) REFERENCES scrolls (id), 
    PRIMARY KEY(id) 
); 

CREATE TABLE IF NOT EXISTS sumarian_wheat_tablet_history 
(
    id   INT NOT NULL auto_increment, 
    foreign_id INT NOT NULL , 
    view_date TIMESTAMP DEFAULT now(), 

    FOREIGN KEY (foreign_id) REFERENCES sumarian_wheat_tablets (id), 
    PRIMARY KEY(id) 
); 

看是否有处理这种情况一个比较正确的做法withou制作n张新桌子?我意识到我可以制作一个history表格并将其复制到CREATE TABLE...LIKE...,但仍需要制作n个新表格,此外我必须进入并ALTERforeign_id

回答

2

我首先想到的是刚刚倾倒FK参考,并有一个历史表:

CREATE TABLE history(
    base_table VARCHAR, 
    base_table_id INT, 
    view_date  TIMESTAMP DEFAULT now() 
); 

但我相信你想要的FK保持完整性(问题:这是非常必要的,还是可以解决这个问题?)。我想你可以通过创建一个“使用中的pks”表来实现这一点。例如:

  • 创建表“键”的列ID(自动增量)和base_table_name
  • 创建表“电影”,其中id是两个PK,也是一个FK到“键。ID”(而不是自动增量列)
  • 添加一个‘插入件之前’触发‘’其中将记录插入‘钥匙’返回生成的ID被用作为ID为‘电影’记录
  • 电影创建一个历史表与FK以“钥匙”
  • 创建一个“删除”触发的“电影”,如果你想完整性维持,或级联删除也删除记录的“钥匙”,等等

所以生成的“id”是在许多表中共享的。有一个思想流派建议使用数据库中所有关系中唯一的主键(“企业关键字”),所以它不是联合国有先例。而不是使用序列或自动生成的列,有时会使用GUID或UUID。

这取代了每个基表上带有触发器的额外历史表,这可能不是一件好事,这取决于您的环境。我自己并没有这样做,只是在那里抛出一些想法,所以拿它的价值。

1

这取决于您保存的记录。如果您只想知道匹配,请在每次满足“匹配”条件时(即从网页读取)添加一个字段到每个表中。如果你想持有更多的信息:

CREATE TABLE IF NOT EXISTS view_history 
(
    id   INT NOT NULL, 
    table  VARCHAR NOT NULL, 
    //other relevant stats to a given view, such as ip and so on. 
) 

id和表格形成一个组合键,关于它引用了什么表。

+0

可以动态引用表吗?即。从'mysql'中选择*。 +'user' – puk

+0

这取决于你如何访问它。这在SQL中可能是可行的,但会很冒险。任何编程语言都可以让你在几个查询中做到这一点。不过,这基本上是ORM所做的。 –

1

我不认为有一种方法可以在单个外键上指定多个表。

如果您定义单个历史记录表,则无法使用单个外键强制执行参照完整性。您可以使用enforce it programmaticaly as explained here

这里描述了如何为不支持FK的其他存储引擎执行此操作,但可以用作实现所需内容的指南。它建议创建触发器来执行外键相同的验证。

其他方法:

CREATE TABLE IF NOT EXISTS history 
(
    id   INT NOT NULL auto_increment, 
    movie_id  INT, 
    book_id  INT, 
    song_id  INT, 
    news_paper_id INT, 
    view_date TIMESTAMP DEFAULT now(), 


    FOREIGN KEY (movie_id) REFERENCES movie (id), 
    FOREIGN KEY (book_id) REFERENCES book (id), 
    FOREIGN KEY (song_id) REFERENCES song (id), 
    FOREIGN KEY (news_paper_id) REFERENCES news_paper (id), 
    PRIMARY KEY(id) 
); 
+0

肯定是矫枉过正,但它完成了工作 – puk