更新中操作获取0或更少时Postgresql引发异常

更新中操作获取0或更少时Postgresql引发异常,postgresql,exception,sql-update,rollback,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

我有三张桌子:

    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
)
我有一个程序可以减少
中的
不能重新启动

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
但有时我在<代码>不能重新启动<代码>中得到0或更少,如果更新结果低于0,我如何进行检查?我不想有负值“/,如果我得到负值,回滚更新并引发异常


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

有更多的可能性:

  • 使用表约束:

    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;
    
    仅创建或替换函数\u正数(数字)
    将数字返回为$$
    开始
    如果$1小于0,则
    引发异常“%s”不是正的,$1;
    如果结束;
    退还$1;
    结束;
    $$语言plpgsql不可变严格;
    
    更新ordencompra_det 设置铁路超高=仅为正值(铁路超高-s.cant\U real)


首选第一种方式。

有更多的可能性:

  • 使用表约束:

    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;
    
    仅创建或替换函数\u正数(数字)
    将数字返回为$$
    开始
    如果$1小于0,则
    引发异常“%s”不是正的,$1;
    如果结束;
    退还$1;
    结束;
    $$语言plpgsql不可变严格;
    
    更新ordencompra_det 设置铁路超高=仅为正值(铁路超高-s.cant\U real)


第一种方法应该是首选的。

事实上我忘了我可以这样做!但是当函数执行时,它会返回一个错误违反检查,我想向用户显示原因,因为他们不能这样做!您可以在触发器之前使用行。当触发器函数返回NULL时,则跳过当前行更新-使用RAISE NOTITE或RAISE WARNING改为引发异常-那么就不会有异常。我做了一个heck函数,现在是解决方案,但是通知警告和异常之间有什么区别呢?通知-打印到调试控制台,警告-打印到控制台和日志,异常-打印到控制台,日志和停止执行。实际上我忘了我可以这么做!但是当函数被执行时,它会返回一个错误违反检查,我想向用户说明原因,因为他们不能这样做!您可以在触发器之前使用一行。当触发器函数返回NULL时,将跳过当前行更新-使用RAISE NOTIONE或RAISE WARNING代替RAISE EXCEPTION-然后将不会出现异常。我做了一个检查现在是解决方案,但是通知警告和异常之间有什么区别呢?通知-打印到调试控制台,警告-打印到控制台和日志,异常-打印到控制台,日志和停止执行。