哪些SQL数据库在CHECK约束中支持子查询?

问题描述

| 哪些SQL数据库(如果有)支持CHECK约束中的子查询? 目前,据我所知,Oracle,MySQL和PostgreSQL还没有。 编辑 (根据初始答案进行澄清。)我正在寻找这样的东西:
CREATE TABLE personnel (
  ...,department VARCHAR(64) NOT NULL,salary NUMERIC NOT NULL,CHECK (salary >= (SELECT MIN(p.salary) FROM payranges p WHERE p.dept = department)
        AND
       salary <= (SELECT MAX(p.salary) FROM payranges p WHERE p.dept = department)
)
更新 MS Access和Firebird均支持此功能。     

解决方法

        Access数据库引擎(ACE,Jet等)在
CHECK
约束中支持子查询,但我犹豫称它为SQL DBMS,因为它不支持入门级标准SQL-92,而MS和Access几乎没有记录Access
CHECK
约束球队。 例如,我可以证明对受影响的每一行都检查了Accessѭ1约束(SQL-92指定应在每个SQL语句之后检查它们),但这是错误还是我们不知道的功能,因为没有相关文档参考。 这是一个包含子查询的CHECK约束的非常简单的示例。它符合Full SQL-92,并且在Access中运行良好。这个想法是将表格限制为最多两行(以下SQL DDL需要ANSI-92查询模式,例如使用ADO连接,例如“ 4”):
CREATE TABLE T1 
(
 c INTEGER NOT NULL UNIQUE
);

ALTER TABLE T1 ADD
   CONSTRAINT max_two_rows
      CHECK (
             NOT EXISTS (
                         SELECT 1
                           FROM T1 AS T
                         HAVING COUNT(*) > 2
                        )
            );
但是,这是可以在Access中创建的另一个示例SQL-92(在Access中某些有效的ѭ1s失败,发生了严重的崩溃,需要重新启动我的机器:(但不能正常工作。这个想法是为了只允许表中恰好两行(或零行:不对空表进行约束测试):
CREATE TABLE T2 
( 
 c INTEGER NOT NULL UNIQUE 
);

ALTER TABLE T2 ADD 
   CONSTRAINT exactly_two_rows 
      CHECK ( 
             NOT EXISTS ( 
                         SELECT 1 
                           FROM T2 AS T 
                         HAVING COUNT(*) <> 2 
                        ) 
            );
尝试在同一条语句中插入两行(假设表
T1
至少有一行):
SELECT DT1.c
  FROM (
        SELECT DISTINCT 1 AS c
          FROM T1
        UNION ALL
        SELECT DISTINCT 2
          FROM T1
       ) AS DT1;
但是,这会导致ѭ1咬住。此(以及进一步的测试)意味着在将每行添加到表之后测试“ 1”,而SQL-92指定在SQL语句级别测试约束。 当您考虑到Access2010之前它没有任何触发器功能并且某些常用表否则没有真正的键时,Access具有真正的表级ѭ1约束就不足为奇了。有效状态时态表中的“已排序”键)。请注意,Access2010触发器遭受的错误/功能与在行级别(而不是语句级别)测试的错误/功能相同。 以下是VBA重现上述两种情况。复制并粘贴到任何VBA / VB6标准.bas模块(例如使用Excel)中,无需引用。在您的temp文件夹中创建一个新的.mdb,创建表,数据和测试约束是否起作用的提示(提示:设置断点,逐步执行代码,阅读注释):
Sub AccessCheckSubqueryButProblem()

  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 T1 \" & vbCr & _
      \"( \" & vbCr & _
      \" c INTEGER NOT NULL UNIQUE \" & vbCr & _
      \");\"
      .Execute Sql

      Sql = _
      \"ALTER TABLE T1 ADD \" & vbCr & _
      \"   CONSTRAINT max_two_rows \" & vbCr & _
      \"      CHECK ( \" & vbCr & _
      \"             NOT EXISTS ( \" & vbCr & _
      \"                         SELECT 1 \" & vbCr & _
      \"                           FROM T1 AS T \" & vbCr & _
      \"                         HAVING COUNT(*) > 2 \" & vbCr & _
      \"                        ) \" & vbCr & _
      \"            );\"
      .Execute Sql

      Sql = _
      \"INSERT INTO T1 (c) VALUES (1);\"
      .Execute Sql

      Sql = _
      \"INSERT INTO T1 (c) VALUES (2);\"
      .Execute Sql

      \' The third row should (and does)
      \' cause the CHECK to bite
      On Error Resume Next
      Sql = _
      \"INSERT INTO T1 (c) VALUES (3);\"
      .Execute Sql
      MsgBox Err.Description
      On Error GoTo 0

      Sql = _
      \"CREATE TABLE T2 \" & vbCr & _
      \"( \" & vbCr & _
      \" c INTEGER NOT NULL UNIQUE \" & vbCr & _
      \");\"
      .Execute Sql

      Sql = _
      \"ALTER TABLE T2 ADD \" & vbCr & _
      \"   CONSTRAINT exactly_two_rows \" & vbCr & _
      \"      CHECK ( \" & vbCr & _
      \"             NOT EXISTS ( \" & vbCr & _
      \"                         SELECT 1 \" & vbCr & _
      \"                           FROM T2 AS T \" & vbCr & _
      \"                         HAVING COUNT(*) <> 2 \" & vbCr & _
      \"                        ) \" & vbCr & _
      \"            );\"
      .Execute Sql

      \' INSERTing two rows in the same SQL statement
      \' should succeed according to SQL-92
      \' but fails (and we have no docs from MS
      \' to indicate whether this is a bug/feature)
      On Error Resume Next
      Sql = _
      \"INSERT INTO T2 \" & vbCr & _
      \"   SELECT c \" & vbCr & _
      \"     FROM T1;\"
      .Execute Sql
      MsgBox Err.Description
      On Error GoTo 0


    End With
    Set .ActiveConnection = Nothing
  End With
End Sub
    ,        Firebird文档说,它允许在CHECK约束中进行子查询。     ,        SQL Server 2000+允许包含查询的UDF:您不能直接使用子查询 但是,它们在高负载下不是并发的     ,        H2还支持约束中的子查询。在Psql模式下:P MariaDB似乎也不支持它作为约束。
ALTER TABLE Table_1 ADD CONSTRAINT constraint_1 
CHECK (column_1 > (SELECT MAX(column_2) FROM Table_2) NOT DEFERRABLE;
  重要说明:由于这本书是关于SQL-99标准的,因此该书及其他页面的内容可能并不直接适用于MariaDB。使用导航栏浏览书籍。      这种事情曾经是非法的,但是在现代的SQL变体中,   您会偶尔看到表间约束引用。 供参考,这是在MariaDB上实施检查约束的票证。截至2015年7月23日,它仍处于“打开”状态。     ,        可以肯定的是,TRIGGER将在您提到的每个数据库中运行,并且您获得更多的“肘部空间”来解决您的约束。     ,        SQL Server支持它 您可以在以下链接中找到有价值的信息 http://www.craigsmullins.com/sql_1298.htm 他们说POSTGRESQL也支持它 http://developer.postgresql.org/pgdocs/postgres/ddl-constraints.html DB2支持CHECK约束 http://www.ibm.com/developerworks/data/library/techarticle/dm-0401melnyk/     

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...