2009-06-04 9 views
1

私の意見を示すにはちょっと面倒ですが、単純な制約で次の表を考えてみましょう。物事を非常に単純に保つために、制約の基準はリテラル値だけを含むことに注意してください。テーブルに少なくとも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)は、UNKNOWNINSERTと評価され、最初の例と同じ理由で成功すると考えられます。

Iは、第二の例における論理は、以下の第三の例と同じであることが期待

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

+0

DDLの代わりにDAOを使ってみてはどうでしょうか? –

+0

2つの理由:1)CHECK制約の作成方法がその機能に影響するとは思わない。 2)DAOを使用してCHECK制約を作成することはできません。 – onedaywhen

+0

...しかしあなたは私に考えを与えた... – onedaywhen

答えて

0

私はバリデーションルール(@デビッドW.フェントン:申し訳ありませんが、私はSQL DDLとADOを見つけて、DAOよりも書き込みしやすいが、インスピレーションのためのおかげで):作成することによって、具体的CHECK制約を排除することができます

Sub TestJetInValidationRule() 

    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 & _ 
      ");" 
     .Execute Sql 
    End With 

    ' Create Validation Rules 
    Dim jeng 
    Set jeng = CreateObject("JRO.JetEngine") 
    jeng.RefreshCache .ActiveConnection 

    .Tables("Test").Columns("ID") _ 
    .Properties("Jet OLEDB:Column Validation Rule").value = _ 
    "5 IN (0, 1, NULL)" 

    jeng.RefreshCache .ActiveConnection 

    With .ActiveConnection 

     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 

    End With 

    Set .ActiveConnection = Nothing 
    End With 
End Sub 

バリデーションルールが噛み付き、INSERTが失敗します。したがって、私はIN句が予期せずに動作していると思われます。私は将来、ネストされたOR句を使用します!

関連する問題