2016-10-08 2 views
0

Я хотел бы использовать одну последовательность для всех первичных ключей в DB2 (10.5 LUW).Создание первичных ключей из одной общей последовательности в DB2

Однако моим слепым глазам не удалось найти способ сделать это. Ближе всего я могу использовать функцию, но она терпит неудачу, когда несколько значений вставляются в один и тот же оператор. Это связано с тем, что функция оценивается только один раз. Мог бы настроить его, добавив зависимость от значений столбцов, но не нравится делать это.

The question relates to my previous one

CREATE SEQUENCE TEST.ID_SEQ AS BIGINT START WITH 10000 INCREMENT BY 1 NO MAXVALUE NO CYCLE CACHE 100 
GO 
--- Bad "hack" since the function is not deterministic 
--- see comments below 
CREATE OR REPLACE FUNCTION TEST.OBJECT_ID() 
    RETURNS BIGINT SPECIFIC TEST.OBJECT_ID 
    CONTAINS SQL DETERMINISTIC NO EXTERNAL ACTION 
    BEGIN 
    DECLARE B BIGINT; 
    SET B = NEXT VALUE FOR TEST.ID_SEQ ; 
    RETURN B ; 
    END 
GO 

CREATE TABLE TEST.TEST (
    ID BIGINT  NOT NULL PRIMARY KEY GENERATED ALWAYS AS (TEST.OBJECT_ID()), 
    TEST VARCHAR(10) 
) 
GO 
+0

Почему вы хотите сделать это? Я имею в виду, что для каждого первичного ключа единственная последовательность не выглядит для меня хорошей идеей, так как это будет горячая точка. – MichaelTiefenbacher

+0

Я хотел бы иметь единственный уникальный идентификатор для всех объектов. Кроме того, разработчики никогда не могут вставлять неправильные внешние ключи (другие pk таблицы) в таблицы, поскольку ключи существуют только один раз. – JMX

+0

Во-первых, ваша функция _not_ детерминирована, потому что она никогда не может вернуть одно и то же значение. Но это не имеет значения - весь ваш подход кажется неправильным. – mustaccio

ответ

0

Вы можете использовать автоинкремент

create table TEST.TEST (
id integer not null GENERATED ALWAYS AS IDENTITY (START WITH 10000 INCREMENT BY 1) 
,TEST varchar(30) 
,PRIMARY KEY (id) 
); 

или использовать вставку как этот

INSERT INTO ORDERS (ORDERNO, CUSTNO) VALUES (NEXT VALUE FOR ORDER_SEQ, 12) 
+0

Спасибо за ответ.Мне бы хотелось получить все идентификаторы от одной и той же последовательности, чтобы первичные ключи были уникальными по таблицам. В другой таблице нет таких же pk. – JMX

+0

Я согласен с Майклом Тифенбахером, это нехороший идеал. Вы также говорите: «Кроме того, разработчики никогда не могут вставлять неправильные внешние ключи (pk) другой таблицы в таблицы, поскольку ключи существуют только один раз», но если вы создадите автоинкремент на всех ваших первичных ключах, у вас не будет этой проблемы. Это система, которая будет управлять ключом – Esperento57

+0

Да, они могут, потому что таблицы имеют одинаковые номера запусков, начиная с 10000 в этом случае .... Идентификаторы уникальны, конечно, в пределах одной таблицы, но не уникальны по всей реализации (редкий случай, но довольно простой используйте pk, взятый из неправильной таблицы). Также получение идентификатора из кэшированной последовательности происходит довольно быстро. Горячая точка не является проблемой в моем случае. – JMX

0

сценарий, который дает пример того, что может быть достаточно для иметь одну таблицу в качестве родительский элемент для нескольких таблиц [это показывает две дочерние таблицы, каждая из которых имеет идентичны ВСТАВИТЬ TRIGGER], через которые каждый из них будет иметь следующее значение последовательности, назначенное от просто одного, таким образом совместно ПОСЛЕДОВАТЕЛЬНОСТИ. Родитель будет, конечно, получить все значения последовательности, и каждый ребенок получит только те значения, которые не в какой-либо другой дочерней таблице:

drop table AppFile01 ; 
drop table AppFile02 ; 
drop table Master_IDENTITY ; 
drop sequence  ID_SEQ ;  

create table Master_IDENTITY 
(Master_ID BIGINT NOT NULL 
, constraint Master_IDENTITY_PK 
    PRIMARY KEY (Master_ID) 
) 
; 
CREATE SEQUENCE  ID_SEQ AS BIGINT 
    START WITH 10000 INCREMENT BY 1  
    NO MAXVALUE NO CYCLE CACHE 100  
; 
create table AppFile01 
(sKeyAF  BIGINT  not null  
, ts   timestamp default current timestamp 
, constraint AppFile01_PK  
    PRIMARY KEY (sKeyAF)  
, constraint AppFile01_FK  
    FOREIGN KEY (sKeyAF)  
    REFERENCES Master_IDENTITY (Master_ID) 
    ON DELETE CASCADE ON UPDATE NO ACTION 
) 
; 
create trigger AppFile01_BI BEFORE INSERT 
on AppFile01  
referencing new as N 
for each row mode db2sql  
begin  
declare NxtSeq BIGINT ; 
set NxtSeq = NEXT VALUE FOR ID_SEQ ; 
insert into Master_IDENTITY values (NxtSeq) ; 
set N.sKeyAF = NxtSeq ; 
end  
; 
create table AppFile02 
(sKeyAF  BIGINT  not null  
, ts   timestamp default current timestamp 
, constraint AppFile02_PK  
    PRIMARY KEY (sKeyAF)  
, constraint AppFile02_FK  
    FOREIGN KEY (sKeyAF)  
    REFERENCES Master_IDENTITY (Master_ID) 
    ON DELETE CASCADE ON UPDATE NO ACTION 
) 
; 
create trigger AppFile02_BI BEFORE INSERT 
on AppFile02  
referencing new as N 
for each row mode db2sql 
begin  
declare NxtSeq BIGINT ; 
set NxtSeq = NEXT VALUE FOR ID_SEQ ; 
insert into Master_IDENTITY values (NxtSeq) ; 
set N.sKeyAF = NxtSeq ; 
end  
; 

И следующие запросы как тестовые и показать эффект; нет особых причин, я решил использовать буквенное значение -1 над, например, DEFAULT:

insert into AppFile01 values(-1, DEFAULT) ; 
; -- gets value 10000  
insert into AppFile02 values(-1, DEFAULT) 
     , (-1, DEFAULT) 
; -- gets values 10001 and 10002 
insert into AppFile01 values(-1, DEFAULT) ; 
; -- gets value 10003  
select * from master_id 
; -- likeness of report from above query 
      MASTER_ID 
      10,000 
      10,001 
      10,002 
      10,003 
select * from appfile01 
; -- likeness of report from above query 
      SKEYAF TS       
      10,000 2016-10-09-18.38.28.347468 
      10,003 2016-10-09-18.38.28.400702 
select * from appfile02 
; -- likeness of report from above query 
      SKEYAF TS       
      10,001 2016-10-09-18.38.28.372121 
      10,002 2016-10-09-18.38.28.386622 
+0

Спасибо @CRPence за решение! Я надеялся сделать это без триггеров, но, скорее всего, никаких других вариантов ... – JMX

+0

А. Я видел, что это было отмечено в связанной теме, но в этой теме не было упоминания о необходимости избегать триггеров. Понятно, что попытка подхода была не спусковой :-), но это похоже на тупик. – CRPence

Смежные вопросы