我有一个表格,我想在其中放置有关文章的所有信息,我需要创建一个包含自动增量的列,如果字段ID
tipo
可以具有相同的值)具有另一个值,对于此特定ID
是唯一的。例如:
ID / TIPO
1 / AJE -- Is Ok
1 / AJS -- Is Ok (because this Tipo is AJS, different from AJE)
1 / SI -- Is Ok
2 / AJE -- Is Ok (New ID)
2 / AJE -- Is Wrong, because ID=2, TIPO=AJE already exist.
我做了这个独特的句子:
ALTER TABLE public.art_movimientos
ADD CONSTRAINT uk_mov UNIQUE (id,tipo) USING INDEX TABLESPACE sistema_index;
但是如何创建覆盖两列的自动增量?
我的表格代码:
CREATE TABLE public.art_movimientos
(
id integer NOT NULL DEFAULT nextval('seq_art_movimientos'::regclass),
tipo character(3) NOT NULL, -- Tipos de Valores:...
documento integer,
fecha_doc date[] NOT NULL,
fecha_mov date[] NOT NULL,
calmacen integer NOT NULL,
status character(13) NOT NULL DEFAULT 'PENDIENTE'::bpchar, -- PENDIENTE...
mes integer NOT NULL,
"año" integer NOT NULL,
donado integer NOT NULL DEFAULT 0
)
WITH (
OIDS=FALSE
);
答案 0 :(得分:1)
您可以使用插入触发器来管理这种情况,模仿@dhke所声明的行为:
CREATE TABLE art_movimientos
(
id integer NOT NULL DEFAULT NULL, -- You don't want a serial, nor a default
tipo character(3) NOT NULL, -- Tipos de Valores:...
documento integer,
fecha_doc date[] NOT NULL,
fecha_mov date[] NOT NULL,
calmacen integer NOT NULL,
status character(13) NOT NULL DEFAULT 'PENDIENTE'::bpchar, -- PENDIENTE...
mes integer NOT NULL,
"año" integer NOT NULL,
donado integer NOT NULL DEFAULT 0,
/* You have actually a 2-column Primary Key */
PRIMARY KEY (tipo, id)
);
-- Create a trigger function to generate 'id'
CREATE FUNCTION art_movimientos_insert_trigger()
RETURNS trigger
AS
$$
BEGIN
/* Compute "id", as the following id for a certain "tipo" */
new.id = coalesce(
(SELECT max(id) + 1
FROM art_movimientos a
WHERE a.tipo = new.tipo), 1);
return new;
END
$$
LANGUAGE 'plpgsql'
VOLATILE ;
-- This trigger will be called whenever a new row is inserted, and "id" is
-- not specified (i.e.: it defaults to null), or is specified as null
CREATE TRIGGER art_movimientos_ins_trg
BEFORE INSERT
ON art_movimientos
FOR EACH ROW
WHEN (new.id IS NULL)
EXECUTE PROCEDURE art_movimientos_insert_trigger();
然后,您可以插入以下行(不带指定id
列):
INSERT INTO art_movimientos
(tipo, documento, fecha_doc, fecha_mov, calmacen, mes, "año")
VALUES
('AJE', 1, array['20170128'::date], array['20170128'::date], 1, 1, 2017),
('AJS', 2, array['20170128'::date], array['20170128'::date], 1, 1, 2017),
('SI', 3, array['20170128'::date], array['20170128'::date], 1, 1, 2017),
('AJE', 4, array['20170128'::date], array['20170128'::date], 1, 1, 2017),
('AJE', 5, array['20170128'::date], array['20170128'::date], 1, 1, 2017) ;
...并且看到你得到了你想要的东西:
SELECT
id, tipo
FROM
art_movimientos
ORDER BY
documento ;
| id | tipo |
|----|------|
| 1 | AJE |
| 1 | AJS |
| 1 | SI |
| 2 | AJE |
| 3 | AJE |
你可以检查一下SQLFiddle(这对PL / pgSQL函数和分号有点挑剔)。
旁注:由于死锁和/或竞争条件,可能会出现一些极端情况,此过程可能会在事务中失败,如果其他事务也同时将数据插入同一个表中。因此,您的整体代码应该能够处理中止的事务,并重试它们或向用户显示错误。