2016-06-10 6 views
1

Ich habe ein Problem mit Trigger in PostgreSQL verwenden, um Barcode zu erstellen. Das Problem ist, dass, wenn die Client-Seite auf meine Web-App zugreift und Daten zur selben Zeit einfügt, ich in einigen meiner Zweckprojekte einen Barcode erzeugen muss. Aber das Problem ist, dass der Auto-generierte Strichcode Duplicate ist. Jede Lösung, bitte hilf mir. Format Strichcode ist: . Das ist mein Auslöser:Duplicate Auto Increment generiert Feld in PostgreSQL mit Trigger

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"(); 

Antwort

1

(Meine Augen geblutet ...) Das ist, was Sie stattdessen tun können, einfach unter Verwendung einer Sequenz (garantiert nicht in irgendwelchen Duplikate entstehen):

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

Es funktioniert. Danke! – munyso

0

versuchen Sie folgendes:

eine Sequenz erstellen:

create sequence test.barcode_sequence_byyear start 1; 

und Ihre Trigger-Funktion:

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; 
Verwandte Themen