哪些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都支持此功能。
答案 0 :(得分:7)
Access数据库引擎(ACE,Jet,等等)支持CHECK
约束中的子查询,但我不愿称之为 SQL DBMS,因为它不支持入门级标准SQL- MS和访问团队几乎没有记录92和访问CHECK
约束。
例如,我可以证明对每个受影响的行检查了Access CHECK
约束(SQL-92指定在每个SQL语句之后应该检查它们)但是这是一个bug还是我们没有的功能知道因为没有可以参考的文件。
这是一个包含子查询的CHECK约束的一个非常简单的例子。它符合Full SQL-92,在Access中运行良好。我们的想法是将表限制为最多两行(以下SQL DDL需要ANSI-92 Query Mode,例如使用ADO连接,例如Access.CurrentProject.Connection
):
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
)
);
但是,这是另一个例子,即SQL-92,可以在Access中创建(一些有效的CHECK
在Access中失败,可怕的崩溃需要我的机器重新启动:(但不是这个想法是只允许表中恰好有两行(或零行:不测试空表的约束):
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;
但是,这会导致CHECK
咬人。这(以及进一步测试)意味着在将每行添加到表之后测试CHECK
,而SQL-92指定在SQL语句级别测试约束。
当您考虑到Access2010之前它没有任何触发功能并且某些经常使用的表会有其它方面时,Access确实存在表级CHECK
约束,这不应该太令人意外。没有真正的密钥(例如,有效状态时态表中的“有序”密钥)。请注意,Access2010触发器遇到的问题与它们在行级别而不是语句级别进行测试相同。
以下是VBA重现上述两种情况。复制并粘贴到任何VBA / VB6标准.bas模块(例如使用Excel),不需要引用。在临时文件夹中创建一个新的.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
答案 1 :(得分:4)
Firebird documentation表示它允许CHECK约束中的子查询。
答案 2 :(得分:2)
SQL Server 2000+允许包含查询的UDF:您不能直接使用子查询
但是,它们不是concurrent under high loads
答案 3 :(得分:1)
H2还支持约束中的子查询。在Psql模式下不少:P
MariaDB 不似乎也支持as a constraint。
ALTER TABLE Table_1 ADD CONSTRAINT constraint_1
CHECK (column_1 > (SELECT MAX(column_2) FROM Table_2) NOT DEFERRABLE;
重要由于本书是关于SQL-99标准的,因此本书中此页面和其他页面的内容可能不会直接应用于MariaDB。使用导航栏导航书籍。
这种事情曾经是非法的,但在SQL的现代版本中, 你偶尔会看到表间约束引用。
供参考,this is the ticket for implementing check constraints on MariaDB。截至2015-07-23,它仍处于“开放”状态。
答案 4 :(得分:0)
非常确定TRIGGER可以在您提到的每个数据库中运行,并且您可以获得更多“肘部空间”来计算您的约束。
答案 5 :(得分:-3)
SQL服务器支持它 您可以在以下链接中找到有价值的信息
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/