2010-03-01 2 views
1

У меня есть таблица, в которой люди были вставив в получении первичного ключа посредством производстваИспользование последовательности в существующей таблице

SELECT max(id)+1 from table_a; 

Я хочу добавить несколько записей в этой таблице, используя INSERT INTO table_a SELECT ... FROM table_b, table_c ... простой SQL сценарий, и мне интересно, как сгенерировать первичные ключи. Моя первая мысль заключалась в создании временной последовательности, но у Oracle, по-видимому, нет select setval, чтобы установить первое значение. Итак, как мне получить текущее значение max (id) +1, чтобы установить параметр «начать с» в мою последовательность?

я нашел что-то он-лайн, что я думал, что будет работать:

COLUMN S new_value st select max(id)+1 S from table_a; 
CREATE SEQUENCE cra_seq start with &st; 

Но это на самом деле не использовать ст в CREATE SEQUENCE, но вместо этого мне подсказывает, чтобы ввести его, что это не то, что мне нужно.

+2

Это побуждает вас ввести параметр, потому что sql * plus выходит из «&». Поместите «set define off» в качестве первой строки вашего скрипта и повторите попытку. –

+1

Будете ли вы когда-нибудь иметь дело, когда в эту таблицу одновременно войдут более одного человека? Если это так, все методы, использующие max (id), будут терпеть неудачу, так как каждый параллельный сеанс будет иметь тот же самый максимальный id. Как просто создать последовательность и использовать ее в качестве источника ваших идентификаторов для всех вставок таблиц? –

+0

@ Ник, поверь мне, я знаю, насколько ужасен метод «select max (id)». Я пытался убедить их перейти к последовательности, но полномочия, которые можно сказать «о, мы переходим на следующий выпуск, поэтому на этот раз это будет нормально». –

ответ

3

Это что-то вроде того, что вы хотите?

1 declare 
    2 id integer; 
    3 begin 
    4 select max(rownum)+1 into id from dual; 
    5 execute immediate 'create sequence myseq start with '||TO_CHAR(id); 
    6* end; 
    7/
+0

Это работает, насколько это возможно, но на следующей строке SQL * Developer жалуется, что строка, начинающаяся с «INSERT», ошибочна, хотя это нормально, если я сам исполняю эту строку. Отчет –

+0

Ошибка: ORA-06550: строка 8, колонка 1: PLS-00103: Обнаружен символ "ВСТАВИТЬ" 06550. 00000 - "линия% s,% s колонки: \ п% s" * Причина: Обычно ошибка компиляции PL/SQL. * Действие: –

+0

Я думаю, вам нужно создать последовательность перед компиляцией процедуры, а затем внутри drop и воссоздать ее. – DCookie

0

Вы можете использовать row_number analytical function для создания номеров строк (от 1 до N).

Прежде чем вставить, введите максимальный идентификатор, который находится в таблице, а затем добавьте номер строки в этот макс, и он правильно заполнит таблицу.

+0

Я понятия не имею, как «получить максимальный id» в sql-скрипте. –

+0

@Paul Tomblin: Предлагаю вам взглянуть на функцию «max» в SQL. – casperOne

+0

Я знаю, как отображать максимальный id, я не знаю, как использовать его так, как вы предлагаете. Похоже, вы говорите о его выборе в переменную, и я не знаю, как вы это делаете в sql-скрипте. –

1

не могли бы вы использовать функцию row_number следующим образом:

Insert Destination(Id, ...) 
Select row_number() over(order by TableA.Col1...) + MaxDestination.MaxId + 1 Num 
, .... 
From TableA, TableB,... 
Cross Join (Select Max(Id) MaxId From Destination) MaxDestination 
+0

Какова цель 'order by col1, col2' там? –

+0

Стреляйте, теперь он говорит, что команда SQL не была правильно закончена. У меня есть 'insert into table_a (id, a, b, c) select row_number() over (order by b) + maxcra.maxid + 1, d, e FROM table_b cross join (выберите max (id) как maxid из table_a) как maxcra где table_b.b = 'FOO'; ' –

+0

Col1, Col2 представляют заполнители для столбца. Команда order by просто сообщает системе, как упорядочить результаты, чтобы определить row_number. Если у вас есть столбец с именем «Имя» и вы хотите, чтобы наименьшее отсортированное имя имело наименьший номер строки, вы должны использовать «Заказ по имени». Я думаю, вам нужно изменить «порядок на b» на «order by table_b.b», однако я буду смотреть дальше. – Thomas

0

В PostgreSQL:

CREATE SEQUENCE new_seq; 
ALTER TABLE existing_table ADD COLUMN new_serial_column bigint DEFAULT 0; 
UPDATE existing_table SET new_serial_column = nextval('new_seq'); 
ALTER TABLE existing_table ALTER COLUMN new_serial_column SET NOT NULL; 
ALTER TABLE existing_table ALTER COLUMN new_serial_column SET DEFAULT nextval('new_seq'); 

Хотя, что код не идемпотентна, поэтому проверьте вы havn't уже создала новую последовательность, что-то вроде:

CREATE FUNCTION fixup_existing_table() RETURNS void AS $$ 
DECLARE 
    new_id bigint; 
    seq_column_exists integer; 
BEGIN 
    SELECT Count(column_name) INTO seq_column_exists FROM information_schema.columns WHERE table_name='existing_table' and column_name='new_serial_column'; 
IF seq_column_exists != 0 THEN RETURN; END IF; 

    CREATE SEQUENCE new_seq; 
    ALTER TABLE existing_table ADD COLUMN new_serial_column bigint DEFAULT 0; 
    UPDATE existing_table SET new_serial_column = nextval('new_seq'); 
    ALTER TABLE existing_table ALTER COLUMN new_serial_column SET NOT NULL; 
    ALTER TABLE existing_table ALTER COLUMN new_serial_column SET DEFAULT nextval('new_seq'); 
END; 
$$ LANGUAGE plpgsql; 

Затем вы можете безопасно позвонить: SELECT fixup_existing_table(), чтобы изменить схему столько раз, сколько захотите, т. Е. Вызывать из некоторого немого сценария обновления.

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