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

时间:2018-07-19 19:54:50

标签: 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 ('product2', '1', '1111111111111');

但是此插入内容会导致错误,因为生产者代码1中已经使用了条形码1111111111111

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位编译”

4 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

使用barcode(而不是输入的“条形码”)插入ProducerCode左填充的字符串

代码看起来像

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

每个Barcode都会产生唯一的ProducerCode

最终数据如下所示

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

请注意第1行和第2行中对应的Barcode重复的ProducerCode

答案 2 :(得分:0)

如果无法更改数据库结构,请更改插入命令

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

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

答案 3 :(得分:0)

如果您可以创建函数和触发器,请在ON BEFORE INSERT触发器中进行操作:

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()

另一方面,看来您没有机会对架构进行任何更改。然后,您必须更改您的INSERT语句。如果要插入的products已应用到另一个bar_code,则可以查看producer_code表。如果满足该条件,则b.*不是NULL,因此将由WHERE子句对其进行过滤。如果没有这种情况,SELECT将获得可以插入的结果。

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 *

RETURNING可以指示是否存在冲突(没有返回行)或没有冲突(返回了插入的行)