私の意見を示すにはちょっと面倒ですが、単純な制約で次の表を考えてみましょう。物事を非常に単純に保つために、制約の基準はリテラル値だけを含むことに注意してください。テーブルに少なくとも1つの列(!!)が必要ですが、その列が制約に含まれていないため、列ID
のみが存在します。ちょっと残念ながら(したがって名前)これは完全に正当な構文であり、SELECT
クエリにWHERE 0 = 1
を追加してゼロ行を返すようにするのと似ています。ACE/JetのIN演算子またはCHECK制約が「壊れていますか?
CREATE TABLE Test1
(
ID INTEGER NOT NULL,
CONSTRAINT daft_1 CHECK (5 = NULL)
);
次INSERT
は成功する(標準SQL DDLコードは、ACE/JetのANSI-92クエリモードで実行されます):
INSERT INTO Test1 (ID) VALUES (1);
これが期待される行動を。述語5 = NULL
は、UNKNOWN
と評価されます。 INSERT
は「疑念の恩恵を受けて」成功しています。問題はない。
IN
演算子を使用して、この同様の例を考えてみましょう:制約が刺されているため
CREATE TABLE Test2
(
ID INTEGER NOT NULL,
CONSTRAINT daft_2 CHECK (5 IN (0, 1, NULL))
);
には、以下のINSERT
は失敗します。
INSERT INTO Test2 (ID) VALUES (1);
は、これは、少なくとも私が、予想外behviourです。 5 IN (0, 1, NULL)
は、UNKNOWN
とINSERT
と評価され、最初の例と同じ理由で成功すると考えられます。
:
CREATE TABLE Test3
(
ID INTEGER NOT NULL,
CONSTRAINT daft_3 CHECK((5 = 0) OR (5 = 1) OR (5 = NULL))
);
以下INSERT
は成功:
INSERT INTO Test3 (ID) VALUES (1);
これは予想される動作です。
私はSQL Server上で3つの例をすべてテストしましたが、すべてが正常に動作しました。つまり、3つすべてINSERT
ステートメントが成功します。実際には、情報スキーマを調べることとして第2の例のSQL Serverの「親切」(grrrが)だから、
((5)=NULL OR (5)=(1) OR (5)=(0))
でIN
演算子を置き換えるために、制約の句を書き換え、ACE /ジェットのために、壊れた「とは何であることが明らかになりました'ここには:IN
演算子またはCHECK
という制約がありますか?
NULL可能な列を使用して問題を再現するためのVBAコードをいくつか示します。また、制約を削除するINSERT
が成功することを可能にすることを実証している:
Sub TestJetInCheck()
On Error Resume Next
Kill Environ$("temp") & "\DropMe.mdb"
On Error GoTo 0
Dim cat
Set cat = CreateObject("ADOX.Catalog")
With cat
.Create _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & _
Environ$("temp") & "\DropMe.mdb"
With .ActiveConnection
Dim Sql As String
Sql = _
"CREATE TABLE Test" & vbCr & _
"(" & vbCr & _
" ID INTEGER, " & vbCr & _
" CONSTRAINT daft_constraint " & vbCr & _
" CHECK (5 IN (0, 1, NULL))" & vbCr & _
");"
.Execute Sql
Sql = "INSERT INTO Test (ID) VALUES (1);"
On Error Resume Next
.Execute Sql
If Err.Number <> 0 Then
MsgBox Err.Description
Else
MsgBox "{{no error}}"
End If
On Error GoTo 0
.Execute "ALTER TABLE Test DROP CONSTRAINT daft_constraint;"
On Error Resume Next
.Execute Sql
If Err.Number <> 0 Then
MsgBox Err.Description
Else
MsgBox "{{no error}}"
End If
On Error GoTo 0
End With
Set .ActiveConnection = Nothing
End With
End Sub
は編集:私はちょうどこれを試して考えた:
SELECT NULL IN(1); - NULLを返します。
SELECT 1(NULL) - はゼロを返します。FALSE
DDLの代わりにDAOを使ってみてはどうでしょうか? –
2つの理由:1)CHECK制約の作成方法がその機能に影響するとは思わない。 2)DAOを使用してCHECK制約を作成することはできません。 – onedaywhen
...しかしあなたは私に考えを与えた... – onedaywhen