6

複数の列に複合キーを作成するにはどうすればよいですか?そのうちの1つは値を持っていても、null(または定数値)を持っていませんか?

例えば:

PK    Loc_ID        Date                Time       Cancelled
1         1         01/01/2010        10:00AM        YES
2         1         01/01/2010        10:00AM        YES
3         1         01/01/2010        10:00AM        null
4         1         01/01/2010        10:00AM        null    - Not Acceptable

4番目のレコードを挿入すると、複合キー違反エラーが発生します。

4

4 に答える 4

6

では、LOC_ID、DATE、TIMEの特定の順列に対して、レコードのみをキャンセルできないルールを適用するにはどうすればよいでしょうか。これは、関数ベースの一意のインデックスを使用して行うことができます。

これは私たちが避けたいことです:

SQL> select * from t34
  2  /

        PK     LOC_ID SOMEDATE   SOMETIM CAN
---------- ---------- ---------- ------- ---
         1          1 01/01/2010 10:00AM YES
         2          1 01/01/2010 10:00AM YES
         3          1 01/01/2010 10:00AM

SQL> insert into t34 
  2  values (4 , 1 , to_date('01/01/2010','DD/MM/YYYY') , '10:00AM', null )
  3  /

1 row created.

SQL>

ルールを適用するためのインデックスを作成しましょう

SQL> rollback
  2  /

Rollback complete.

SQL> create unique index t34_uidx 
  2  on t34 (loc_id, somedate, some_time, nvl2(cancelled, pk, null) )
  3  /

Index created.

SQL>

このNVL2()関数は、最初の引数がNOT NULLの場合は2番目の引数を返し、それ以外の場合は3番目の引数を返すCASEの特殊な形式です。インデックスはPKcolを2番目の引数として使用します。これは、PK colが主キーであり、したがって一意であるためです。したがって、インデックスは、nullでない限り、CANCELEDの重複値を許可します。

SQL> insert into t34 
  2  values (4 , 1 , to_date('01/01/2010','DD/MM/YYYY') , '10:00AM', null )
  3  /
insert into t34 values (4 , 1 , to_date('01/01/2010','DD/MM/YYYY') , '10:00AM', null )
*
ERROR at line 1:
ORA-00001: unique constraint (APC.T34_UIDX) violated


SQL>
于 2010-07-30T15:32:42.230 に答える
1

これは、一意の関数ベースのインデックスを使用して実行できますか?何かのようなもの:

create unique index ix on tb (
    loc_id, date, time, decode(cancelled, null, 1, null));
于 2010-07-30T15:22:55.550 に答える
1

LOC_ID、DATE_COL、および TIME_COL の特定の組み合わせに対して 1 つの NULL だけが値を取り消すというルールの場合:

SQL> create table EXAMPLE
  2  (  PK        number       not null,
  3     LOC_ID    number       not null,
  4     DATE_COL  date         null,
  5     TIME_COL  varchar2(10) null,
  6     CANCELLED varchar2(3)  null,
  7     constraint EXAMPLE_PK primary key (PK)
  8  );

Table created.

SQL>
SQL> create unique index EXAMPLE_UK01 on EXAMPLE
  2    (case when CANCELLED is null then LOC_ID   else null end,
  3     case when CANCELLED is null then DATE_COL else null end,
  4     case when CANCELLED is null then TIME_COL else null end
  5  );

Index created.

SQL>
SQL> INSERT INTO EXAMPLE VALUES
  2    (1, 1, DATE '2010-01-01', '10:00AM', 'YES');

1 row created.

SQL>
SQL> INSERT INTO EXAMPLE VALUES
  2    (2, 1, DATE '2010-01-01', '10:00AM', 'YES');

1 row created.

SQL>
SQL> INSERT INTO EXAMPLE VALUES
  2    (3, 1, DATE '2010-01-01', '10:00AM', null);

1 row created.

SQL>
SQL> INSERT INTO EXAMPLE VALUES
  2    (4, 1, DATE '2010-01-01', '10:00AM', null);
INSERT INTO EXAMPLE VALUES
*
ERROR at line 1:
ORA-00001: unique constraint ([schema].EXAMPLE_UK01) violated
于 2010-07-30T15:36:40.983 に答える
0

これがOracleで有効かどうかはわかりませんが、Postgresqlでは、nullの列を除いて、nullの部分的な複数列インデックスでこれを行うことができます。

CREATE UNIQUE INDEX idx_foo
ON example ( Loc_ID, Date, Time )
WHERE canceled IS NULL
于 2010-07-30T15:15:40.793 に答える