2016-06-10 73 views
1

我在PostgreSQL中使用觸發器創建條形碼時遇到問題。問題是,當客戶端訪問我的Web應用程序並在同一時間插入數據時,我需要在我的一些目標項目中生成條形碼。但問題是Auto生成的條形碼是Duplicate。任何解決方案,請幫助我。格式條碼是:。 這是我的觸發器:使用觸發器在PostgreSQL中重複自動增量生成字段

DROP TABLE IF EXISTS "test"."barcode"; 
CREATE TABLE "test"."barcode" (
"id" int8 DEFAULT nextval('"test".t_id_seq'::regclass) NOT NULL, 
"barcode" varchar(255) COLLATE "default" 
) 
WITH (OIDS=FALSE); 

----------------------------------------- 

CREATE OR REPLACE FUNCTION test.my_trigger_function() 
    RETURNS trigger AS 
$BODY$DECLARE new_barcode CHAR(50); 

BEGIN 
    SELECT 
    (CASE 
     WHEN 
      CHAR_LENGTH (CAST(CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1 AS CHAR(20))) = 1 THEN 
       (SUBSTRING(barcode, 1, 4) || '00000000' || CAST((CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1) AS CHAR(20))) 
     WHEN 
      CHAR_LENGTH (CAST(CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1 AS CHAR(20))) = 2 THEN 
       (SUBSTRING(barcode, 1, 4) || '0000000' || CAST((CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1) AS CHAR(20))) 
     WHEN 
      CHAR_LENGTH (CAST(CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1 AS CHAR(20))) = 3 THEN 
       (SUBSTRING(barcode, 1, 4) || '000000' || CAST((CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1) AS CHAR(20))) 
     WHEN 
      CHAR_LENGTH (CAST(CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1 AS CHAR(20))) = 4 THEN 
       (SUBSTRING(barcode, 1, 4) || '00000' || CAST((CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1) AS CHAR(20))) 
     WHEN 
      CHAR_LENGTH (CAST(CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1 AS CHAR(20))) = 5 THEN 
       (SUBSTRING(barcode, 1, 4) || '0000' || CAST((CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1) AS CHAR(20))) 
     WHEN 
      CHAR_LENGTH (CAST(CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1 AS CHAR(20))) = 6 THEN 
       (SUBSTRING(barcode, 1, 4) || '000' || CAST((CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1) AS CHAR(20))) 
     WHEN 
      CHAR_LENGTH (CAST(CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1 AS CHAR(20))) = 7 THEN 
       (SUBSTRING(barcode, 1, 4) || '00' || CAST((CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1) AS CHAR(20))) 
     WHEN 
      CHAR_LENGTH (CAST(CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1 AS CHAR(20))) = 8 THEN 
       (SUBSTRING(barcode, 1, 4) || '0' || CAST((CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1) AS CHAR(20))) 
     WHEN 
      CHAR_LENGTH (CAST(CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1 AS CHAR(20))) = 9 THEN 
       (SUBSTRING(barcode, 1, 4) || CAST((CAST(SUBSTRING(barcode, 5, 9) AS INTEGER) + 1) AS CHAR(20))) 
     ELSE 
      (CAST((CAST(TO_CHAR(NOW(),'yyyy') AS INTEGER)+1) AS CHAR(20)) || '000000001') 
    END 
    ) INTO new_barcode 
FROM 
    test. barcode 
ORDER BY 
    id DESC 
LIMIT 1; 

IF new_barcode IS NULL THEN 
    new_barcode = (CAST(TO_CHAR(NOW(),'yyyy') AS CHAR(20)) || '000000001'); 
END IF; 
    NEW.barcode = new_barcode; 
    RETURN NEW; 
END;$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 
ALTER FUNCTION test.my_trigger_function() 
    OWNER TO postgres; 
-------------------------------------------------- 

CREATE TRIGGER "my_trigger" BEFORE INSERT ON "test"."barcode" 
FOR EACH ROW 
EXECUTE PROCEDURE "test"."my_trigger_function"(); 

回答

1

(我的眼睛流血......)這是你可以做什麼,而不是,只需使用序列(保證不以任何重複收取):

CREATE SEQUENCE IF NOT EXISTS test.barcode_seq START 2016000000001; 

CREATE OR REPLACE FUNCTION test.my_trigger_function() RETURNS trigger AS 
$BODY$ 
DECLARE 
    _barcode bigint; 
BEGIN 
    _barcode := nextval('test.barcode_seq'); 

    IF EXTRACT('year' FROM CURRENT_DATE) <> _barcode/1000000000 THEN 
    _barcode := EXTRACT('year' FROM CURRENT_DATE) * 1000000000 + 1; 
    PERFORM setval('test.barcode_seq', _barcode, true); 
    END IF; 

    NEW.barcode = _barcode::text; 
    RETURN NEW; 
END; 
$BODY$ LANGUAGE plpgsql; 
+0

它的工作原理。謝謝! – munyso

0

試試這個:

創建一個序列:

create sequence test.barcode_sequence_byyear start 1; 

和你的觸發功能:

CREATE OR REPLACE FUNCTION test.my_trigger_function() 
RETURNS trigger AS 
$BODY$DECLARE new_barcode CHAR(50); 
    declare count_barcode_of_year integer; 

BEGIN 
--If it is the first barcode of year then init sequence to 1 
    select count(*) into count_barcode_of_year from test.barcode where barcode like to_char(now(),'YYYY')||'%'; 
    if count_barcode_of_year=0 then 
     --set sequence to 1 
     PERFORM setval('test.barcode_sequence_byyear'::regclass,1,false); 
    end if; 

    --Format your new barcode with year and sequence (YEAR + Sequence with 9 significatives zeros : 
    NEW.barcode=to_char(now(),'YYYY')||to_char(nextval('test.barcode_sequence_byyear'::regclass),'FM'||repeat('0',9)); 
    RETURN NEW; 
END;$BODY$ 
LANGUAGE plpgsql VOLATILE 
COST 100; 
ALTER FUNCTION test.my_trigger_function() 
OWNER TO postgres; 
相關問題