Reputation: 413
I am encountering the error "argument of AND must not return a set" from the AND
in the check constraint of the below table.
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
)
);
The implementation of CurrentStudentLoansCount()
is shown below.
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;
Why am I running into this error and how can I work around it?
For context, the below figure displays my database schema.
Upvotes: 1
Views: 1008
Reputation:
Your function returns a table with multiple rows so you can't use that for a BETWEEN condition. Presumably you just want that value for the account_id of that row of the table (not for all account_ids).
So change the function to return a single value by passing it the account_id. And you also don't need PL/pgSQL for this:
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;
And change your table definition to:
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)
);
Upvotes: 3