代码之家  ›  专栏  ›  技术社区  ›  onedaywhen

ACE/Jet是否在操作员或检查约束中“断开”?

  •  1
  • onedaywhen  · 技术社区  · 17 年前

    ID 仅存在,因为表必须至少有一列(!!),但该列不包含在约束中。虽然有点愚蠢(因此得名),但这是完全合法的语法,类似于添加 WHERE 0 = 1 SELECT 查询以确保返回零行。

    (标准SQL DDL代码,将在ACE/Jet的ANSI-92查询模式下执行)

    CREATE TABLE Test1 
    (
       ID INTEGER NOT NULL, 
       CONSTRAINT daft_1 CHECK (5 = NULL)
    );
    

    以下 INSERT 成功:

    INSERT INTO Test1 (ID) VALUES (1);
    

    这是预期的行为。谓词 5 = NULL 应评估为 UNKNOWN 插入 被“给予怀疑的好处”并成功。没问题。

    IN 接线员:

    CREATE TABLE Test2 
    (
       ID INTEGER NOT NULL, 
       CONSTRAINT daft_2 CHECK (5 IN (0, 1, NULL))
    );
    

    以下 插入 失败,因为约束咬合:

    INSERT INTO Test2 (ID) VALUES (1);
    

    5 IN (0, 1, NULL) 再次被评估为 未知的 成功的原因与第一个例子相同。

    我希望第二个示例中的逻辑与以下第三个示例相同:

    CREATE TABLE Test3
    (
       ID INTEGER NOT NULL, 
       CONSTRAINT daft_3 CHECK((5 = 0) OR (5 = 1) OR (5 = NULL))
    );
    

    以下 插入 成功:

    INSERT INTO Test3 (ID) VALUES (1);
    

    我已经在SQL Server上测试了所有这三个示例,并按照我的预期进行了测试,即所有这三个示例 声明成功了。事实上,检查信息模式可以发现,对于第二个示例,SQL Server as“helpfully”(grrr)重写了约束的子句以替换 在里面 接线员

    ((5)=NULL OR (5)=(1) OR (5)=(0))
    

    那么,对于ACE/Jet来说,这里的“坏”是什么呢 在里面 接线员或 CHECK 限制

    下面是一些VBA代码,使用可为空的列来重现问题;还演示了删除约束允许 插入 要成功:

    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
    

    编辑:我只是想试试这个:

    在(1)中选择空;

    在中选择1(空) --返回零,即FALSE

    1 回复  |  直到 17 年前
        1
  •  1
  •   onedaywhen    17 年前

    我可以消除 CHECK 特别是通过创建验证规则来约束(@David W.Fenton:对不起,我发现SQL DDL和ADO比DAO更容易编写,但感谢您的启发):

    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
    

    验证规则被咬住并插入失败。因此,我怀疑IN子句的行为出人意料。将来我将使用嵌套或子句!

    推荐文章