Oracle

如何在 Oracle 中的 CASE 表達式上創建索引

  • June 20, 2021

我正在嘗試在 oracle 表上創建索引,如下所示

DECLARE MGMT_ID NUMBER;
       SSHKEY_MGMT_ID NUMBER;

BEGIN
   SELECT ID INTO MGMT_ID FROM POLICY_SETS WHERE POLICY_SET_NAME = 'MGMT';
   SELECT ID INTO SSHKEY_MGMT_ID FROM POLICY_SETS WHERE POLICY_SET_NAME = 'SSHKEY_MGMT';

   CREATE UNIQUE INDEX PASSWORD_OBJECT_UI_1
       ON PASSWORD_OBJECTS (ACCOUNTNAME, ADDRESS,
       (CASE
           WHEN POLICY_SET = MGMT_ID OR POLICY_SET = SSHKEY_MGMT_ID THEN 1
           ELSE 0
       END
       )
   );
   COMMIT;
END;
/

問題是我得到了錯誤:

SQL Error [6550] [65000]: ORA-06550: line 8, column 5:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:

最後,但並非最不重要的一點是,我必須提到這個腳本的目標是對錶 PASSWORD_OBJECTS 創建一個限制(這將確保列(ACCOUNTNAME,ADDRESS)的組合具有唯一性,只有一個例外:

  • 當表的 2 個條目(行)具有相同的列組合(ACCOUNTNAME,ADDRESS)並且一個條目在(MGMT,SSHKEY_MGMT)中具有 POLICY_SET 列,而另一個條目的 POLICY_SET 列不在(MGMT,SSHKEY_MGMT)中時的情況。

這將是兩行可以組合具有相同值(ACCOUNTNAME,ADDRESS)的唯一情況。

有任何想法嗎?如果您認為我對索引的想法是 KO,我願意接受其他技術解決方案。

表 DDL 和範例數據將有助於檢查這是否符合您的要求,但語法工作版本將是:

declare
   mgmt_id          number;
   sshkey_mgmt_id   number;
   create_index_sql varchar2(200);
begin
   select id into mgmt_id
   from   policy_sets
   where  policy_set_name = 'MGMT';

   select id into sshkey_mgmt_id
   from   policy_sets
   where  policy_set_name = 'SSHKEY_MGMT';

   create_index_sql :=
   'create unique index password_object_ui_1 on password_objects'||
   '( accountname, address'||
   ', (case when policy_set in ('||mgmt_id||','||sshkey_mgmt_id||') then 1 else 0 end) )';
   
   dbms_output.put_line(create_index_sql);
   
   execute immediate create_index_sql;
end;

這給出了(有一點重新格式化):

create unique index password_object_ui_1 on password_objects
( accountname
, address
, (case when policy_set in (123, 321) then 1 else 0 end) )

引用自:https://dba.stackexchange.com/questions/294499