Проверьте ограничение Вызов функции Разработчик Oracle SQL

Возможно ли в Oracle SQL разработчику сделать что-то подобное

CREATE FUNCTION fnCheckValid(accountidd IN NUMBER) 
RETURN NUMBER 
   IS retval NUMBER(4,0);
   BEGIN 
      SELECT COUNT(accountid_fk) 
      INTO retval 
      FROM tbl_AccountAuthentications 
      WHERE accountid_fk = accountidd; 
      RETURN(retval); 
    END;
/


ALTER TABLE tbl_AccountAuthentications
ADD CONSTRAINT chkCheckvalid CHECK(fnCheckValid(accountid_fk) 
 Oliver Ciappara27 мая 2013 г., 21:05
редактировать с тем, что я хочу сделать, такжеSYS» был там, как тест забыл удалить его, но все еще есть эта ошибка после удаления 'SYS»
 Oliver Ciappara27 мая 2013 г., 21:31
Отредактировано с запрошенными данными, да, они находятся в одной таблице
 Dan Bracuk27 мая 2013 г., 21:27
Находятся ли обычные и открытые счета в одной таблице?
 Dan Bracuk27 мая 2013 г., 20:59
Вы просто пытаетесь убедиться, что accountid_fk уникален?
 Oliver Ciappara27 мая 2013 г., 22:04
Если кто-то может помочь мне в этом, я был бы признателен также за использование триггеров, но мне не удалось это сделать, если кто-то может помочь мне в создании успешного триггера или в устранении ошибки в этом утверждении, я предполагаю, что его потому что я использую Oracle SQL Developer 11G, но не уверен, если у вас есть какой-либо другой способ решить эту просьбу пожалуйста обратно :) спасибо!
 Bob Jarvis28 мая 2013 г., 02:06
Ограничения CHECK в Oracle не могут вызывать пользовательские функции. СсылкаВот.

Ответы на вопрос(2)

Решение Вопроса

AccountID а такжеRegularIDвместе являются уникальными, независимо от того, сколькоOpenID имеются.

Единственный способ сделать это, как вымы определилисдерживать Это. Вы отмечаете в комментариях, что выМы экспериментировали с триггерами. Это делаетне ограничить значения в базе данных, это только гарантирует, что он пытается проверить, когда триггер включен. Я ожидаю, что, когда вы попытались, вы получили ошибку "ORA-04091: мутирует, триггер / функция могут его не видеть. " как и ты'выбираете из таблицы, которую вынаходятся в процессе изменения (вставить или обновить).

Если вы должны ограничить это, то этоs что вы должны сделать; проблема в том, что ваша таблица не нормализована. Итак, нормализуй это. Используйте две таблицы вместо той, которая у вас есть.

Во-первых, вам нужен вашRegularID быть уникальным надAccountID это означает, что он должен храниться на этом уровне. Кажется, будтоtbl_UserAccounts уникален по этому идентификатору, поэтому измените эту таблицу и сохранитеRegularID там.

Далее вы хотите таблицу, которая имеет как можно большеOpenID S, как пользователь может хотеть. Это означает, что вам нужен уникальный столAccountID а такжеOpenID 1.

create table openid_account_auth (
   , account_id number(4,0)
   , open_id number(4,0)
   , constraint pk_openid_account_auth
       primary key (account_id, open_id)
   , constraint fk_openid_account_auth_accid
       foreign key (account_id)
       references tbl_UserAccounts(account_id)
   , constraint fk_openid_account_auth_open
       foreign key (open_id)
       references tbl_OpenID (openid)
     );

Одна точка в этой таблице (и ваша собственная) означает, что несколько учетных записей могут иметь одинаковыеOpenID, Если вы не собирались этого делать, добавьтеAccountID в качестве внешнего ключа вtbl_OpenIDчто было бы единственным способом гарантировать, что каждыйOpenID ассоциируется с одним и только одним,AccountID.

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

create or replace view AccountAuthentications as
 select account_id, regular_id, null
   from user_accounts
  union all
 select account_id, null, open_id
   from openid_account_auth;

Проще говоря, если нет строгих ограничений, вы всегда должны хранить данные в нем »s естественный уровень и использовать базу данных для обеспечения целостности. Если вам нужно использовать данные немного по-другому, вы можете использовать представления илиматериализованные взгляды и т.д., чтобы сделать это.

1. Яизвините, но я могуЯ ставлю перед собой префикс имени каждой таблицы.tbl_

Ограничения на проверку ограничений:

Вызовы пользовательских функций

Но вы можете сделать обходной путь, используя виртуальные столбцы

ALTER TABLE tbl_AccountAuthentications ADD (fnCheck NUMBER GENERATED ALWAYS AS (fnCheckValid(accountid_fk)) VIRTUAL);


ALTER TABLE tbl_AccountAuthentications
ADD CONSTRAINT chkCheckvalid CHECK(fnCheck <= 1);

Обратите внимание, что функция должна быть ДЕТЕРМИНИСТИЧЕСКОЙ, иначе она не работает. Oracle не проверяет, является ли ваша функция действительно детерминированной, она просто проверяет ключевое слово. Это разрешено (хотя это не имеет никакого смысла):

CREATE OR REPLACE FUNCTION DET_FUNCTION RETURN NUMBER DETERMINISTIC IS 
BEGIN 
    RETURN DBMS_RANDOM.RANDOM();
END;
/
 Alex Poole04 янв. 2017 г., 16:29
Стоит ли упоминать, что это все еще допустимо, только если функция является детерминированной? А в 12с виртуальная колонка может быть невидимой.

Ваш ответ на вопрос