Reputation: 3460
I'm attempting to get the last SERIAL ID
created in a table by usingpg_get_serial_sequence()
in a procedure, but I keep getting an error:
[42P01]ERROR: relation "user" does not exist
Where: SQL function "insert_new_user" statement 2
The User
table certainly exists, as I can SELECT
from it.
Below is the DDL script for creating the 2 tables being effected by my function:
CREATE TABLE users.User
(
ID SERIAL PRIMARY KEY,
Name TEXT NOT NULL UNIQUE,
EmailAddress TEXT,
ROWCREATE_TS TIMESTAMP,
IS_ACTIVE BOOLEAN,
INACTIVE_TS TIMESTAMP
);
CREATE TABLE users.Credential
(
CredentialValue TEXT,
UserId INT REFERENCES users.User(ID)
);
And here is the procedure that is returning the error:
/**
Creates a new user
*/
CREATE OR REPLACE PROCEDURE users.INSERT_NEW_USER(userName TEXT, emailAddress TEXT, password TEXT)
LANGUAGE SQL
AS $$
INSERT INTO users.User
(
NAME,
EmailAddress,
ROWCREATE_TS,
IS_ACTIVE
)
SELECT
INSERT_NEW_USER.userName,
INSERT_NEW_USER.emailAddress,
CURRENT_TIMESTAMP,
TRUE
WHERE
NOT EXISTS(
SELECT TRUE
FROM users.User
WHERE
NAME = INSERT_NEW_USER.userName
);
INSERT INTO users.Credential
(
CREDENTIALVALUE,
USERID
)
VALUES
(
INSERT_NEW_USER.password,
(SELECT currval(pg_get_serial_sequence('user', 'id')))
);
$$;
(NOTE: Before someone mentions it - I do not plan on storing passwords here in plain text.)
What can I do differently to either address this issue of pg_get_serial_sequence
not recognizing the User
table, or to ultimately get that last created ID stored into a usable variable that I can pass into my INSERT INTO users.Credential
statement?
Upvotes: 1
Views: 766
Reputation: 3460
This was solved by using a combination of suggestions in the comments.
I had renamed the table, as User
is a PostgreSQL keyword, and also used the fully qualified name users.NewTableName
within the pg_get_serial_sequence()
call, as shown below.
SELECT currval(pg_get_serial_sequence('users.NewTableName', 'id'))
.
EDIT: It could be worth pointing out, for future readers with a similar issue, that the following also worked as a fix to my goal of getting that ID down to the 2nd statement. I was able to do it using WITH
:
CREATE OR REPLACE PROCEDURE users.INSERT_NEW_USER(userName TEXT, emailAddress TEXT, password TEXT)
LANGUAGE SQL
AS $$
WITH Inserted as(
INSERT INTO users.Users
(
NAME,
EmailAddress,
ROWCREATE_TS,
IS_ACTIVE
)
SELECT
INSERT_NEW_USER.userName,
INSERT_NEW_USER.emailAddress,
CURRENT_TIMESTAMP,
TRUE
WHERE
NOT EXISTS(
SELECT TRUE
FROM users.Users
WHERE
NAME = INSERT_NEW_USER.userName
)
RETURNING ID
)
INSERT INTO users.Credential
(
CREDENTIALVALUE,
USERID
)
VALUES
(
INSERT_NEW_USER.password,
(SELECT Inserted.ID FROM Inserted)
);
$$;
With that said, I would also like to advise readers that they should avoid using PostgreSQL keywords for naming tables, variables, etc.
Upvotes: 2