2013-07-12 5 views
-2

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

+2

Вы можете просто определить столбец, чтобы быть' 'unique' и не null_! – NINCOMPOOP

+0

Да, я знаю, что могу, но я хочу узнать, как производится первичный ключ (это, конечно же, триггер). Я хочу создать свой собственный триггер, который должен работать так же, как первичный ключ. –

+0

Почему вы думаете первичный ключ реализуется как триггер под капотом? Ограничения и триггеры - это совсем другие вещи. –

ответ

1

Основной ключ не является спусковым крючком. Это ключ, потому что он идентифицирует всю строку, поэтому она должна быть уникальной (и неявно не нулевой). Он является «основным», потому что именно ключ кандидата является наиболее подходящим - по вашему решению - основным справочным ключом для вашей таблицы. Вы можете добавить его как ALTER TABLE your_table_name ADD CONSTRAINT PK_your_table_name PRIMARY KEY (your_key_column).

Если вы не хотите добавлять первичный ключ (это плохая идея), но хотите добавить уникальный индекс в эту таблицу: CREATE UNIQUE INDEX UQ_IX_your_table_your_column ON your_table_name (unique_column_name). Ограничение NOT NULL должно быть помещено в столбец.

+0

Да, только первичный ключ - это ключ кандидата, который наиболее подходит (по вашему решению), чтобы быть основным реферированием ce ключ для вашего стола. Я должен был ответить на этот вопрос, извините. – Koshinae

+0

Спасибо за головы! – Koshinae

+0

вы идете совершенно неправильно! Я не спрашиваю, как определить ключи и их использование. –

2

«я хочу, чтобы узнать, как первичный ключ состоит из (это триггер, конечно)»

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

Если вы хотите узнать, что правила довольно просты: не нуль, уникальность, сериализация. Поэтому просто попробуйте реализовать первичный ключ в триггерах. Вы обнаружите, что не можете (оповещение о спойлере!) Из-за проблемы «мутирующего стола». И если вы не понимаете, что это значит, хорошо, что есть хорошая тема для чтения.


есть вопрос «это не представляется возможным определить триггер, который проверяет значение перед установкой, что он не должен быть нулевым и уникальным, а?»

Ответ на этот вопрос: Нет. Ну, вы можете закодировать реализацию на основе триггера, но, как и другие «мутирующие таблицы», для этого потребуются триггеры операторов пакета и AFTER (так технически не до вставки).

А если серьезно, какой смысл? Вы не узнаете ничего о том, как работают первичные ключи. И мутирующие таблицы почти всегда указывают на плохую модель данных, и это, безусловно, будет иметь место здесь.

+0

спасибо APC. мне ясно, что это не спусковой механизм. да, будет мутировавшее условие. возникает вопрос: «Невозможно определить триггер, который проверяет значение перед вставкой, что он также не должен быть нулевым и уникальным?» –

2

Просто потому, что вы, кажется, намерены видеть это не так, и не принимать ничего от точек APC, это, кажется, работает на первый взгляд, пока это before триггер:

create table t42 (id number); 

create trigger trig42 
before insert or update on t42 
for each row 
declare 
    c number; 
begin 
    if :new.id is null then 
    raise_application_error(-20001, 'ID is null');  
    end if; 
    select count(*) into c from t42 where id = :new.id; 
    if c > 0 then 
    raise_application_error(-20002, 'ID is not unique'); 
    end if; 
end; 
/

Он компилирует и если вы вставляете данные, которые у вас получаете поведение, которое вам кажется нужным:

insert into t42 values (1); 

1 rows inserted. 

insert into t42 values (1); 

Error starting at line 20 in command: 
insert into t42 values (1) 
Error report: 
SQL Error: ORA-20002: ID is not unique 
ORA-06512: at "STACKOVERFLOW.TRIG42", line 9 
ORA-04088: error during execution of trigger 'STACKOVERFLOW.TRIG42' 

insert into t42 values (null); 

Error starting at line 22 in command: 
insert into t42 values (null) 
Error report: 
SQL Error: ORA-20001: ID is null 
ORA-06512: at "STACKOVERFLOW.TRIG42", line 5 
ORA-04088: error during execution of trigger 'STACKOVERFLOW.TRIG42' 

select * from t42; 

     ID 
---------- 
     1 

Это похоже на то, что вы хотите. Но нет, если у вас более одного сеанса. Я не участвовал в этой сессии; в другой сессии я могу сделать:

insert into t42 values (1); 

1 row created. 

select * from t42; 

     ID 
---------- 
     1 

1 row selected. 

Хм, это странно. Ну, может быть, это отложено ... давайте сделаем их обоим:

commit; 

select * from t42; 
     ID 
---------- 
     1 
     1 

2 rows selected. 

Oops. После того, как сеанс не сможет увидеть незафиксированные данные другого сеанса, это никогда не будет работать.

Кроме того, проблема Mutating таблица показывает себя, когда мы вставляем несколько строк в одном операторе:

SQL> insert into t42 select level+1 from dual connect by level <= 5; 
insert into t42 select level+1 from dual connect by level <= 5 
      * 
ERROR at line 1: 
ORA-04091: table STACKOVERFLOW.T42 is mutating, trigger/function may not see it 
ORA-06512: at "STACKOVERFLOW.TRIG42", line 7 
ORA-04088: error during execution of trigger 'STACKOVERFLOW.TRIG42' 


SQL> 

Double упс.

Даже с триггером after и проблемой для работы с проблемой мутирующего стола у вас все равно будет эта проблема (я думаю), если вы не заблокируете всю таблицу для каждой вставки или обновления. Как сказал APC, ограничение выполняется глубоко в недрах базы данных, а не на этом уровне.

Невозможно определить триггер, который проверяет значение до ввода , что оно не должно быть нулевым и уникальным?

Не когда у вас более одной сессии, нет. И даже в течение одного сеанса, если у вас нет индекса в столбце, производительность не будет масштабироваться, так как count(*) будет постепенно замедляться. И если у вас есть индекс, ну, почему бы не сделать его уникальным индексом в первую очередь?

Наконец, из trigger design guidelines:

Не создавать триггеры, которые дублируют функции базы данных.

Например, не создать триггер, чтобы отклонить неправильные данные, если вы можете сделать то же самое с ограничениями (см "How Triggers and Constraints Differ").

+0

Я удивлен, что этот триггер скомпилирован и выполнен (в частности, «выполнено» " часть). Учитывая, что он представляет собой триггер строки, который делает SELECT в таблице, на которой он определен, я ожидал, что он получит ошибку «mutating table». Что мне здесь не хватает? –

+0

@Bob - Я тоже был удивлен, но я так избегаю триггеров, что не был уверен, что это повлияет только на триггеры - не думайте так. Может быть, стол, пустой, имеет значение, но он еще не знал этого? Если я помню, я постараюсь расследовать на следующей неделе. –

+0

большое спасибо. вы объяснили очень хорошо и подробно. спасибо большое –

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