如何确保两列始终相同

时间:2014-09-24 21:58:24

标签: sql postgresql database-design normalization

我有一个包含很多行的表,但是name和id列总是需要相同的相对于彼此。

示例:

name      id      value
'josh'     1      'blah'
'josh'     1      'foo'
'marc'     2      'bar'
'marc'     2      'boo'

在任何时候都不应该有一个名为'josh'的行,其中id!= 1,但组合可能会重复多次(因此它不是主键)。

4 个答案:

答案 0 :(得分:4)

此数据看起来没有规范化。

如果您仍然可以更改表格设计,我会创建一个单独的表格:

create table example_people (
    id int not null primary key,
    -- unique constraint fixes problem identified by philipxy
    name varchar not null unique
)

然后将现有表重新定义为:

create table example_value (
    id int not null,
    value varchar,
    constraint fk_value foreign key (id) references example_people (id)
);

检查整个表的触发器的替代方案通常执行得相当差,因为它必须序列化写访问。

答案 1 :(得分:2)

这就是我要做的事情:

  1. 使用name和id(PK)创建表,并将名称检查为唯一

  2. 创建一个包含值的表和第一个

  3. 的外键

答案 2 :(得分:0)

您可以使用

查找错误数据
SELECT id, FROM your_table
GROUP BY id HAVING count(first_name)>1;

和id和first_name的类似查询被颠倒了。我想你也可以加入UNION。但正如Laurence和Jose所说,你应该做的是将ID和Name拉入一个单独的表中,并只使用其中一个作为外键。

答案 3 :(得分:0)

问题的根源是functional dependency id -> name,违反了3NF

您可以通过将表格分成两部分来解决它:

CREATE TABLE name_table (
    id int PRIMARY KEY,
    name varchar(50) NOT NULL UNIQUE
);

CREATE TABLE value_table (
    value varchar(50) PRIMARY KEY,
    id int NOT NULL REFERENCES name_table
);

您可以轻松地重建"原始表通过JOIN,您可以将其包装到VIEW或存储过程(DBMS相关)等。

顺便说一下,试着找出比这更好的名字!另外,请考虑向value_table添加surrogate key是否值得。