Sql 如何为不同的生产商代码禁用相同的条形码

Sql 如何为不同的生产商代码禁用相同的条形码,sql,postgresql,constraints,postgresql-9.1,unique-constraint,Sql,Postgresql,Constraints,Postgresql 9.1,Unique Constraint,Postgres 9.1.2数据库包含产品表 create table product ( ProductCode char(10) primary key, ProducerCode char(15), BarCode char(13) ); 如何仅允许相同的生产商代码使用相同的条形码。 例如,这些值是有效的: INSERT INto product values ('product1', '1', '1111111111111'); INSERT INto product values (

Postgres 9.1.2数据库包含产品表

create table product (
ProductCode char(10) primary key,
ProducerCode char(15),
BarCode char(13) );
如何仅允许相同的生产商代码使用相同的条形码。 例如,这些值是有效的:

INSERT INto product values ('product1', '1', '1111111111111');
INSERT INto product values ('product2', '1', '1111111111111');
但由于生产商代码1中已使用条形码1111111,因此此插入操作将导致错误

INSERT INto product values ('product3', '2', '1111111111111');
使用


“x86_64-unknown-linux-gnu上的PostgreSQL 9.1.2,由gcc-4.4.real(Debian 4.4.5-8)4.4.5编译,64位”

您的数据结构错误。您应该有两个表:

create table product (
    ProductCode char(10) primary key,
    BarCode char(13)
);

create table BarCode (
    BarCode char(13) primary key,
    ProducerCode char(15)
);
此结构将自动保证条形码最多有一个
ProducerCode

注意:我建议不要使用字符串作为主键,而是首选
serial
char()
特别奇怪,除非您确定列的长度是固定的

编辑:

或者:

create table product (
    ProductCode char(10) primary key,
    ProducerCode char(15)
);

create table ProducerCodes (
    ProducerCode char(15) primary key,
    BarCode char(13) primary key unique
);

这也应该做你想做的。请注意,
BarCode
可以是
NULL

使用
ProducerCode
而不是输入的“BarCode”在
BarCode
中插入一个左填充字符串

代码看起来像

INSERT INTO Product ( ProductCode , ProducerCode , BarCode ) 
VALUES ('product1' , '1' , LPAD('1' , 13 , '0'))
将为每个
ProducerCode

最终数据如下所示

('product1' , '1' , '0000000000001');
('product2' , '1' , '0000000000001');
('product3' , '2' , '0000000000002');

请注意第1行和第2行中对应的
ProducerCode
重复的
Barcode
,如果无法更改数据库结构,请更改insert命令

INSERT INTO product select 'product3', '2', '1111111111111' where '1111111111111' not in (select barcode from product) returning *

然后检查返回的内容以确定插入是否成功

是否可以创建函数和触发器在插入前的
打开中执行该操作
触发器:

CREATE FUNCTION error_on_barcode_at_another_producer()  RETURNS trigger
    VOLATILE
AS $body$
BEGIN
    IF EXISTS (
            SELECT 1 FROM products p 
            WHERE p.bar_code = NEW.bar_code AND p.producer_code <> NEW.producer_code) THEN
       RAISE EXCEPTION 'bar_code is already linked to another producer_code';
    END IF;

    RETURN NEW;
END;
$body$ LANGUAGE plpgsql

CREATE TRIGGER tr_error_on_barcode_at_another_producer
    BEFORE INSERT OR UPDATE ON products
    FOR EACH ROW
EXECUTE PROCEDURE error_on_barcode_at_another_producer()

返回
可以指示是否存在冲突(未返回行)或不存在冲突(已返回插入行)

此条形码是针对生产商还是针对产品?我之前说错了独特性。我不明白你的答案。您能提供使用answer中的数据实现此功能的示例代码吗?请给我第二个答案。否。条形码是在车间分配的,对于相同的生产商代码是相同的。
插入产品值('product3','2','1111')命令应该没有错误。如何实现这一点?此外,条形码值应该是
1111111111
,而不是像您的回答中那样。不幸的是,我无法更改数据库结构。如何使用问题中的表结构实现此功能?答案假定条形码始终存在。这是错误的。条形码可能为空,并且只能指定ProducerCode。答案似乎不符合该假设-如果条形码为空,则表BarCode中将没有行。如果有条形码,则它将被强制属于一个且仅属于一个生产者。更新的答案假定ProducerCode不为空。ProducerCode也可以为空。如果条形码和ProducerCode都可能为空,如何使用此答案?
INSERT INTO products

SELECT 
    a.* 
FROM
    (SELECT 'product3' AS product_code, '2' AS producer_code, '1111111111111' AS bar_code) a --your values here
LEFT JOIN products b
ON a.bar_code = b.bar_code AND a.producer_code <> b.producer_code
WHERE b.product_code IS NULL

RETURNING *