Postgresql 如何创建根据另一列的值增加的列

Postgresql 如何创建根据另一列的值增加的列,postgresql,field,auto-increment,unique-constraint,Postgresql,Field,Auto Increment,Unique Constraint,我有一个表,我想在其中放置有关文章使用的所有信息,我需要使用autoincrement创建一个列,如果字段tipo有另一个值,则ID可以具有相同的值,该值对于该特定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

我有一个表,我想在其中放置有关文章使用的所有信息,我需要使用autoincrement创建一个列,如果字段tipo有另一个值,则ID可以具有相同的值,该值对于该特定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
);

您可以通过使用插入前触发器来管理这种情况,模拟@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)
)

然后,可以插入以下行,而无需指定id列:

。。。确保你得到你想要的:

SELECT 
    id, tipo 
FROM 
    art_movimientos 
ORDER BY 
    documento ;


| id | tipo |
|----|------|
|  1 |  AJE |
|  1 |  AJS |
|  1 |  SI  |
|  2 |  AJE |
|  3 |  AJE |
您可以检查对PL/pgSQL函数和分号有点挑剔的所有内容


旁注:如果其他事务也在同一时间将数据插入同一个表中,可能会有一些情况下,由于死锁和/或竞争条件,此过程在事务中可能会失败。因此,您的总体代码应该能够处理中止的事务,并重试这些事务或向用户显示错误。

与“不这样做吗?”?如果PK的值不依赖于表的内容(在本例中是这样),则序列非常有用。您可能会更好地使用INSERT INTO art_Movimentos选择maxid+1,tipo。。。来自art_Movimentos,其中tipo=“…”。因此,您建议使用bigserial字段,并仅设置一个主键?这通常更容易,并且一行对应一个键。刚才,您可以有一行AJE123,它恰好是最后一行,您可以删除它,然后插入一个新的行。它将再次获得AJE123。两个不同事物的相同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 |