查询 Firebird 3.0 中的变量
Variables in queries Firebird 3.0
此查询无效
select a.id from users a where a.LOGIN = 'Test' into :useriden
WITH T AS (
SELECT
ID,
FIO,
PWDHASH,
ATTIME,
ROW_NUMBER() OVER(ORDER BY ATTIME DESC) AS RN
FROM USERSPWDHASHHISTORY
WHERE USERID = :useriden)
SELECT
ID,
FIO,
PWDHASH,
ATTIME
FROM T
WHERE RN > 3
如何正确初始化数据库查询中的变量?不在存储过程或触发器中。
你想要的在 DSQL 中无法完成,在 PSQL 中这至少是一个语法错误,因为你没有终止语句。
但是,您不需要为此单独声明,您可以内联查询
WITH T AS (
SELECT
ID,
FIO,
PWDHASH,
ATTIME,
ROW_NUMBER() OVER(ORDER BY h.ATTIME DESC) AS RN
FROM USERSPWDHASHHISTORY
WHERE USERID = (select a.id from users a where a.LOGIN = 'Test'))
SELECT
ID,
FIO,
PWDHASH,
ATTIME
FROM T
WHERE RN > 3
或使用联接而不是 sub-query
WITH T AS (
SELECT
h.ID,
h.FIO,
h.PWDHASH,
h.ATTIME,
ROW_NUMBER() OVER(ORDER BY ATTIME DESC) AS RN
FROM USERSPWDHASHHISTORY h
inner join users u on h.userid = u.id
WHERE u.LOGIN = 'Test')
SELECT
ID,
FIO,
PWDHASH,
ATTIME
FROM T
WHERE RN > 3
或者,您首先 select id,然后使用 ?
id 参数占位符准备其他查询,使用您 selected 的 id 值准备并执行它以前。
例如,在 Java 中,您可以执行以下操作:
int id = -1;
try (var stmt = connection.createStatement();
var rs = rs.executeQuery("select a.id from users a where a.LOGIN = 'Test'")) {
if (rs.next()) {
id = rs.getInt(1);
}
}
try (var stmt = connection.prepareStatement("""
WITH T AS (
SELECT
ID,
FIO,
PWDHASH,
ATTIME,
ROW_NUMBER() OVER(ORDER BY ATTIME DESC) AS RN
FROM USERSPWDHASHHISTORY
WHERE USERID = ?)
SELECT
ID,
FIO,
PWDHASH,
ATTIME
FROM T
WHERE RN > 3
""")) {
stmt.setInt(1, id);
try (var rs = stmt.executeQuery()) {
// process result set
}
}
但是,鉴于此特定示例可以在一个语句中完成,考虑到执行两个语句和相关网络往返的不必要开销,这种解决方案不是首选。
此查询无效
select a.id from users a where a.LOGIN = 'Test' into :useriden
WITH T AS (
SELECT
ID,
FIO,
PWDHASH,
ATTIME,
ROW_NUMBER() OVER(ORDER BY ATTIME DESC) AS RN
FROM USERSPWDHASHHISTORY
WHERE USERID = :useriden)
SELECT
ID,
FIO,
PWDHASH,
ATTIME
FROM T
WHERE RN > 3
如何正确初始化数据库查询中的变量?不在存储过程或触发器中。
你想要的在 DSQL 中无法完成,在 PSQL 中这至少是一个语法错误,因为你没有终止语句。
但是,您不需要为此单独声明,您可以内联查询
WITH T AS (
SELECT
ID,
FIO,
PWDHASH,
ATTIME,
ROW_NUMBER() OVER(ORDER BY h.ATTIME DESC) AS RN
FROM USERSPWDHASHHISTORY
WHERE USERID = (select a.id from users a where a.LOGIN = 'Test'))
SELECT
ID,
FIO,
PWDHASH,
ATTIME
FROM T
WHERE RN > 3
或使用联接而不是 sub-query
WITH T AS (
SELECT
h.ID,
h.FIO,
h.PWDHASH,
h.ATTIME,
ROW_NUMBER() OVER(ORDER BY ATTIME DESC) AS RN
FROM USERSPWDHASHHISTORY h
inner join users u on h.userid = u.id
WHERE u.LOGIN = 'Test')
SELECT
ID,
FIO,
PWDHASH,
ATTIME
FROM T
WHERE RN > 3
或者,您首先 select id,然后使用 ?
id 参数占位符准备其他查询,使用您 selected 的 id 值准备并执行它以前。
例如,在 Java 中,您可以执行以下操作:
int id = -1;
try (var stmt = connection.createStatement();
var rs = rs.executeQuery("select a.id from users a where a.LOGIN = 'Test'")) {
if (rs.next()) {
id = rs.getInt(1);
}
}
try (var stmt = connection.prepareStatement("""
WITH T AS (
SELECT
ID,
FIO,
PWDHASH,
ATTIME,
ROW_NUMBER() OVER(ORDER BY ATTIME DESC) AS RN
FROM USERSPWDHASHHISTORY
WHERE USERID = ?)
SELECT
ID,
FIO,
PWDHASH,
ATTIME
FROM T
WHERE RN > 3
""")) {
stmt.setInt(1, id);
try (var rs = stmt.executeQuery()) {
// process result set
}
}
但是,鉴于此特定示例可以在一个语句中完成,考虑到执行两个语句和相关网络往返的不必要开销,这种解决方案不是首选。