0

元の質問

したがって、私が作成していないビジネス モデルには、オプションの関係があります (ER モデルのように)。DBの仕事を始めてしばらく経っているので、何か忘れているかもしれません。現在、1 番目のテーブルの FK (外部キー) は、ID である 2 番目のテーブルの PK (主キー) を指しています。この用語は覚えていませんが、RDBMS (リレーショナル データベース管理システム) で使用される「本物の」用語ではなく、「偽の」用語です。簡単にするために、テーブルが 2 つだけあるとします。

現在、オプションの関係が必要ない場合、FK 列/属性に null があります。その列にアイテムがある場合、完全な利点が必要であり、関係の反対側に一致するアイテムがあるかどうかを確認し、FK が指している場所 (2 番目のテーブル) もトリガーします (ただし、現在はありません)。検証。少し前までは1番目のテーブルの重要な部分を重複させたくないことに気付いたので満足していたので、一意のキーを作成したかったのですが、列/属性を含むキーは作成できないようですnull が含まれる場合があります。どちらも理解していませんが、これまでのところ2つの解決策が提案されています。

1 つ目は、数字ベースの型には 0 を、文字ベースの型には空の文字列 ('') をデフォルトとして設定したことです。私が得られないのは、2番目のテーブルに対応する値(0)を持つ行/タプルがすでにあるということです。現在の行をシフトしてデフォルトの行がないようにする場合は、対応するコンテンツにもデフォルトを入れると思います。私の場合は文字ベースのタイプです。したがって、インデックスを有効にする「コスト」は、多数の役に立たない結合を作成してから、ソフトウェアによる多数の役に立たないマージを行うことです。私の場合は、オフィス スイートのデータベース セクションであるApache OpenOffice Baseです。これは多くの処理が追加されているように見えます。現在の設計に加えて、ある種のトリガーの方が良いように思えます。

2つ目は、多対多の関係である「リンクされた」テーブル(彼/彼女の用語)を作成することでしたが、それらは1つ以上の可能な関係を持つエントリ専用だと思いました。0 対 1 の関係がある場合は使用されません。とにかく、その「リンクされた」テーブルにエントリを含める必要がないという同じ問題に直面することになります。IIRC、そのようなテーブルの 2 つの「側面」には、有効な候補キーが含まれている必要があります。

そのため、ビジネス モデルでそのオプションが必要な場合に備えて、1 対 1 の関係は既に実装されており、FK の現在の null 以外のエントリがあります。ここで、ビジネス モデルがオプションの部分を必要としない場合のメソッドを実装して、0-1 の関係を許可し、FK の現在の null エントリに対して重複を許可しないようにする必要があります。

どうぞよろしくお願いいたします。

フレッドリクエスト

これには3番目の例が含まれています。

次のサブセクションには、コマンドを使用した Apache OpenOffice Base からのセミ SQL エクスポートが含まれていますSCRIPT 'PATH\TO\NAME.sql'。元のファイルとそのエクスポート、およびエクスポートされていないクエリは、How to make an index with an optional FK? にあります。例 3

ID_to_part1 、model_number、および ID_to_part2 の 3 つの列/属性に一意のキーが必要です。ただし、前のセクションの元の質問では、HSQLDB バージョン 1.8.0.10 では、一意のキーの一部である列に null を含めることができないことが示されています。

HSQLDB エクスポート

ある種の SQL を生成します。非標準的なステートメントを含みます。

SET DATABASE COLLATION "Latin1_General"
CREATE SCHEMA PUBLIC AUTHORIZATION DBA
CREATE CACHED TABLE "Table1"("ID" INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,"ID_to_part1" INTEGER NOT NULL,"model_number" VARCHAR_IGNORECASE(3) NOT NULL,"ID_to_part2" INTEGER)
CREATE CACHED TABLE "Table2"("ID" INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,"content" VARCHAR_IGNORECASE(1) NOT NULL)
CREATE CACHED TABLE "Table3"("ID" INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,"content" VARCHAR_IGNORECASE(1) NOT NULL)
ALTER TABLE "Table1" ADD CONSTRAINT SYS_FK_87 FOREIGN KEY("ID_to_part1") REFERENCES "Table3"("ID") ON DELETE CASCADE ON UPDATE CASCADE
ALTER TABLE "Table1" ADD CONSTRAINT SYS_FK_90 FOREIGN KEY("ID_to_part2") REFERENCES "Table2"("ID") ON DELETE SET NULL ON UPDATE CASCADE
ALTER TABLE "Table1" ALTER COLUMN "ID" RESTART WITH 15
ALTER TABLE "Table2" ALTER COLUMN "ID" RESTART WITH 2
ALTER TABLE "Table3" ALTER COLUMN "ID" RESTART WITH 4
CREATE USER SA PASSWORD ""
GRANT DBA TO SA
SET WRITE_DELAY 0 MILLIS
SET SCHEMA PUBLIC
INSERT INTO "Table1" VALUES(0,0,'123',0)
INSERT INTO "Table1" VALUES(1,1,'456',NULL)
INSERT INTO "Table1" VALUES(2,2,'789',0)
INSERT INTO "Table1" VALUES(3,0,'012',1)
INSERT INTO "Table1" VALUES(6,3,'345',NULL)
INSERT INTO "Table1" VALUES(7,1,'678',1)
INSERT INTO "Table1" VALUES(8,0,'123',NULL)
INSERT INTO "Table1" VALUES(9,0,'123',1)
INSERT INTO "Table1" VALUES(10,1,'456',0)
INSERT INTO "Table1" VALUES(11,1,'456',1)
INSERT INTO "Table1" VALUES(12,1,'456',0)
INSERT INTO "Table1" VALUES(13,1,'123',NULL)
INSERT INTO "Table1" VALUES(14,1,'123',0)
INSERT INTO "Table2" VALUES(0,'B')
INSERT INTO "Table2" VALUES(1,'E')
INSERT INTO "Table3" VALUES(0,'A')
INSERT INTO "Table3" VALUES(1,'C')
INSERT INTO "Table3" VALUES(2,'D')
INSERT INTO "Table3" VALUES(3,'F')

クエリがエクスポートされていないようです。ここでは、クエリの後に結果が続きます

クエリ1

参加したメイン テーブル:

SELECT "Table1"."ID", "Table3"."content" AS "Table3_content", "Table1"."model_number", "Table2"."content" AS "Table2_content"
    FROM "Table1"
        LEFT OUTER JOIN "Table2" ON "Table1"."ID_to_part2" = "Table2"."ID"
        LEFT OUTER JOIN "Table3" ON "Table1"."ID_to_part1" = "Table3"."ID"
    ORDER BY "ID" ASC

結果:

ID    Table3_content    model_number    Table2_content
0     A                 123             B
1     C                 456             
2     D                 789             B
3     A                 012             E
6     F                 345             
7     C                 678             E
8     A                 123             
9     A                 123             E
10    C                 456             B
11    C                 456             E
12    C                 456             B
13    C                 123             
14    C                 123             B

クエリ2

一意のインデックスの 2 つの最初の部分が目的の一意のインデックスを「壊す」可能性がある行/タプルは、3番目も一致する必要があります。つまり、他の行は脅威ではありません (Query1 から Query2 を引いたもの)。

SELECT *
    FROM "Table1"
    -- It seem HSQLDB won't support tuples as in WHERE (col1, col2) IN ( SELECT col1, col2 FROM
    WHERE "ID_to_part1" IN (
            SELECT "ID_to_part1"
                FROM "Table1"
                GROUP BY "ID_to_part1", "model_number"
                HAVING COUNT(*) > 1
        ) AND "model_number" IN (
            SELECT "model_number"
                FROM "Table1"
                GROUP BY "ID_to_part1", "model_number"
                HAVING COUNT(*) > 1
        )
    ORDER BY "ID_to_part1" ASC, "model_number" ASC, "ID_to_part2" ASC, "ID" ASC

結果:

ID    ID_to_part1    model_number    ID_to_part2
8     0              123             
0     0              123             0
9     0              123             1
13    1              123             
14    1              123             0
1     1              456             
10    1              456             0
12    1              456             0
11    1              456             1

クエリ3

目的の一意のインデックスを「壊す」行/タプル。

SELECT "Table1".*
    FROM "Table1"
        JOIN (
            SELECT "ID_to_part1", "model_number", "ID_to_part2"
                FROM "Table1"
                GROUP BY "ID_to_part1", "model_number", "ID_to_part2"
                HAVING COUNT(*) > 1
        ) AS "non_unique_model"
            ON "Table1"."ID_to_part1"="non_unique_model"."ID_to_part1"
                AND "Table1"."model_number"="non_unique_model"."model_number"
                AND "Table1"."ID_to_part2"="non_unique_model"."ID_to_part2"
    ORDER BY "ID_to_part1" ASC, "model_number" ASC, "ID_to_part2" ASC, "ID" ASC

結果:

ID    ID_to_part1    model_number    ID_to_part2
10    1              456             0
12    1              456             0

重要なテーブル スキーマの美化

CREATE CACHED TABLE "Table1"(
    "ID" INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,
    "ID_to_part1" INTEGER NOT NULL,
    "model_number" VARCHAR_IGNORECASE(3) NOT NULL,
    "ID_to_part2" INTEGER
)
CREATE CACHED TABLE "Table2"(
    "ID" INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,
    "content" VARCHAR_IGNORECASE(1) NOT NULL
)
4

3 に答える 3

1

SOへようこそ!あなたの質問は少し読みにくいと思います。

編集:

CREATE TABLE table1 (
    id INTEGER NOT NULL PRIMARY KEY,
    data1 INTEGER NOT NULL
);

CREATE TABLE table2 (
    id INTEGER NOT NULL PRIMARY KEY REFERENCES table1(id),
    data2 INTEGER NOT NULL
);

table1 にレコードがあります。table1 の各レコードに対して、table2 には対応するレコードが 0 個または 1 個あります。

このパターンは、テーブルの継承に似ています。

さらなる説明:

これにより、次のデータが必要になります。

id   data1         id  data2
----------         ---------
 0    1234          0     42
 1    5678          2     57
 2    9012

ID 0 と 2 を持つ table1 のレコードに対応するレコードが table2 にあることを確認します。ID 1 のレコードはそうではありません。

PS

物事を 1 つのテーブルに結合することもできることに注意してください。これが望ましいかどうかは、状況によって異なります。

CREATE TABLE table1 (
    id INTEGER NOT NULL PRIMARY KEY,
    data1 INTEGER NOT NULL,
    data2 INTEGER NULL
);
于 2013-10-26T21:41:41.563 に答える
0

一意のキーを作成したかったのですが、null を含む可能性のある列を含むキーを作成できないようです。

私の理解では、パフォーマンスを向上させるためにインデックスを作成する FK があり、FK には null が含まれている可能性があります (@Paul Draper のソリューションのように)。

私は HSQLDB の専門家ではありませんが、ユーザー ガイドの Constraints セクションには次のように書かれています。 UNIQUE 制約列のいずれかの値は NULL であり、常にテーブルに追加できます。そのため、値の 1 つが NULL の場合、複数の行に UNIQUE 列の同じ値を含めることができます。 "

これは、FK 値を持つ行を含む列が Null であっても、データベースのバージョン 1.7.2 で FK にインデックスを作成できることを意味すると理解しています。

于 2013-10-26T21:58:15.210 に答える
0

あなたの質問は:

1番目のテーブルの重要な部分を重複させたくなかったので、一意のキーを作成したかったのですが、nullを含む可能性のある列を含むキーを作成できないようです。

Table1 の「重要な部分」に重複は必要ありませんが、どの部分を一意にする必要があるかは明確ではありません。「重要な部分」が次の 3 つの列の一部であると仮定します。

"ID_to_part1" INTEGER,"model_number" VARCHAR_IGNORECASE(3) NOT NULL,"ID_to_part2" INTEGER

A) "model_number" に一意の制約を作成する場合、これは定義上 NOT NULL です。

CONSTRAINT UNIQUE ("model_number")

この場合、model_number の値は一意ですが、2 つの異なるモデルが同じ ID_to_part1 を持つことができます

B) (A) に加えて、次の制約を設定できます。

CONSTRAINT UNIQUE ("model_number", "ID_to_part1")

次に、各 model_number が一意の ID_to_part1 に対応します。ID_to_part1 に NOT NULL がない場合は、余分な部分を持たない model_number 値に NULL を含めることができます。

C)(A)に加えて、これを持つことができます:

CONSTRAINT UNIQUE ("model_number", "ID_to_part2")

(B) と同じ効果がありますが、ID_to_part2 列に対してです。

あなたのSELECTステートメントは正しいです。すべてのモデルがオプション情報とともに表示されます。

つまり、NULL を持つことができる列に UNIQUE 制約を設定できます。ただし、model_number に対する UNIQUE 制約も必要です。

編集:

OPは、「model_number」が一意ではないという要件で質問を再度編集しました。3つの列のみが一意であり、そのうちのいくつかはNULLを格納でき、NULLを繰り返すことはできません。これは、HSQLDB 1.8 では実現できません。HSQLDB 2.x には、これを許可するために FALSE に変更できる SET DATABASE SQL UNIQUE NULLS の設定があります。この場合、3 つの列に必要な UNIQUE 制約は 1 つだけです。

于 2013-10-29T17:12:43.100 に答える