首页 > 解决方案 > 在检查约束中与 BETWEEN 一起使用时,AND 的参数不能返回一个集合

问题描述

AND在下表的检查约束中遇到错误“AND 的参数不能返回集合”。

CREATE TABLE loan (
   id SERIAL PRIMARY KEY,
   copy_id INTEGER REFERENCES media_copies (copy_id),
   account_id INT REFERENCES account (id),
   loan_date DATE NOT NULL,
   expiry_date DATE NOT NULL,
   return_date DATE,

   CONSTRAINT max_student_concurrent_loans CHECK(
      CurrentStudentLoansCount() BETWEEN 1 AND 7 
   )
);

的实现CurrentStudentLoansCount()如下图所示。

CREATE OR REPLACE FUNCTION CurrentStudentLoansCount()
RETURNS TABLE(accid BIGINT) AS $$
BEGIN
   RETURN QUERY
   SELECT COUNT(*)
   FROM loan
   WHERE account_id IN (SELECT id FROM student)
      AND return_date IS NULL
   GROUP BY account_id;
END
$$ LANGUAGE PLPGSQL;

为什么我会遇到此错误,我该如何解决?

对于上下文,下图显示了我的数据库架构。 数据库模式

标签: sqlpostgresql

解决方案


您的函数返回一个包含多行的表,因此您不能将其用于 BETWEEN 条件。大概您只想要表中该行的 account_id 的值(不是所有的 account_id)。

因此,通过将 account_id 传递给函数来更改函数以返回单个值。而且你也不需要PL/pgSQL:

CREATE OR REPLACE FUNCTION currentstudentloanscount(p_account_id integer)
  RETURNS bigint
as
$$
  SELECT COUNT(*)
  FROM loan
  WHERE account_id = p_account_id
    AND return_date IS NULL;
$$ LANGUAGE sql;

并将您的表定义更改为:

CREATE TABLE loan (
   id SERIAL PRIMARY KEY,
   copy_id INTEGER REFERENCES media_copies (copy_id),
   account_id INT REFERENCES account (id),
   loan_date DATE NOT NULL,
   expiry_date DATE NOT NULL,
   return_date DATE,

   CONSTRAINT max_student_concurrent_loans 
       CHECK(currentstudentloanscount(account_id) BETWEEN 1 AND 7)
);

推荐阅读