更新时操作获得0或更少时的Postgresql RAISE EXCEPTION

时间:2017-03-24 18:20:02

标签: postgresql exception sql-update rollback

我有三张桌子:

    CREATE TABLE public.art_movimientos
    (
      cmovimiento bigint NOT NULL DEFAULT nextval('art_movimientos_cmovimiento_seq'::regclass),
      tipo character varying(3) NOT NULL, -- Tipos de Valores:...
      fecha_mov timestamp without time zone NOT NULL,
      documento integer NOT NULL,
      control integer,
      fecha_doc timestamp without time zone NOT NULL,
      corden integer NOT NULL DEFAULT 0,
      calmacen integer NOT NULL,
      calmacen2 integer,
      status character varying(13) NOT NULL DEFAULT 'PENDIENTE'::bpchar, -- PENDIENTE...
      donado integer NOT NULL DEFAULT 0,
      monto_mov numeric(11,2) NOT NULL DEFAULT 0.00,
      monto_desc numeric(11,2) NOT NULL DEFAULT 0.00,
      monto_total numeric(11,2) NOT NULL DEFAULT 0.00,
      observacion text,
      casiento integer,
      crea_user character varying(25),
      crea_date timestamp without time zone,
      mod_user character varying(25),
      mod_date timestamp without time zone,
      cproveedor integer NOT NULL DEFAULT 0
    )
CREATE TABLE public.art_movimientos_det
(
  cmovimiento_det bigint NOT NULL DEFAULT nextval('art_movimientos_det_cmovimiento_det_seq'::regclass),
  cmovimiento integer NOT NULL,
  cart_generico integer NOT NULL,
  cunidad integer NOT NULL DEFAULT 1,
  cant numeric(11,2) NOT NULL DEFAULT 0.00,
  iva numeric(11,2) NOT NULL DEFAULT 0.00,
  costou numeric(11,2) NOT NULL DEFAULT 0.00,
  crea_user character varying(25),
  crea_date timestamp without time zone,
  mod_user character varying(25),
  mod_date timestamp without time zone,
  cart_comercial integer NOT NULL,
  costot numeric(11,2) NOT NULL DEFAULT 0.00
)
CREATE TABLE public.ordencompra_det
(
  corden_det bigint NOT NULL DEFAULT nextval('ordencompra_det_corden_det_seq'::regclass),
  corden integer NOT NULL,
  cart_comercial integer NOT NULL,
  cunidad integer NOT NULL DEFAULT 1,
  cant numeric(11,2) NOT NULL DEFAULT 0.00,
  costou numeric(11,2) NOT NULL DEFAULT 0.00,
  iva numeric(11,0) NOT NULL DEFAULT 0.00,
  costot numeric(11,2) NOT NULL DEFAULT 0.00,
  crea_user character varying(25),
  crea_date timestamp without time zone,
  mod_user character varying(25),
  mod_date timestamp without time zone,
  cant_restante numeric(11,2) NOT NULL DEFAULT 0
)

我有一个减少cant_restante中的ordencompra_det的程序:

UPDATE ordencompra_det AS od
        SET cant_restante = cant_restante - s.cant_real
        FROM (SELECT am.corden, md.cart_comercial,(md.cant*u.multiplicador)cant_real FROM art_movimientos am INNER JOIN art_movimientos_det md ON am.cmovimiento=md.cmovimiento INNER JOIN art_und u ON md.cunidad=u.cunidad WHERE md.cmovimiento=cmov) AS s
        WHERE od.corden=s.corden and od.cart_comercial=s.cart_comercial

但有时我在cant_restante得到0或更少,我如何检查,如果更新结果低于0?我不想有负值“/,如果我得到负值,回滚更新并引发异常?

我正在使用postgresql函数(程序)(因为我在数据库中做了很多事情)

1 个答案:

答案 0 :(得分:1)

还有更多可能性:

  • 使用表约束:

    CREATE TABLE ordencompra_det(
      ...
      cant_restante numeric(11,2) NOT NULL DEFAULT 0 CHECK(can_restante >= 0),
      ...
    )
    
  • 使用检查功能:

    CREATE OR REPLACE FUNCTION only_positive(numeric)
    RETURNS numeric AS $$
    BEGIN
      IF $1 < 0 THEN
        RAISE EXCEPTION '%s is not positive', $1;
      END IF;
      RETURN $1;
    END;
    $$ LANGUAGE plpgsql IMMUTABLE STRICT;
    

    更新ordencompra_det   SET cant_restante = only_positive(cant_restante - s.cant_real)   ...

第一种方式应该是首选。