你好,
我们如何跨两个不同的模式但相同的数据库实现表连接。
从技术上讲,模式只是同一数据库中表的逻辑分离,因此在编写 SQL 查询时,我们只需要在它们前面加上模式名称即可。
例如,
select *
from user_schema.users as users
inner join account_schema.accounts as accounts
on users.users.id = accounts.user_id
我可能会写在 kenx.js 下面。 那看起来不错吗?
knex.from('user_schema.users as users').innerJoin('account_schema.accounts as accounts',
'users.id', 'accounts.user_id')
但后来我看到了。 withSchema
选项与 knex.js 使用该选项而不是在表名前加上模式有什么好处。 如何使用.withSchema
选项连接来自两个不同模式的连接表?
Knex.js Documentation
------------------------
.withSchema([schemaName])
Specifies the schema to be used as prefix of table name.
knex.withSchema('public').select('*').from('users')
Outputs:
select * from `public`.`users`
这个有什么解决方案吗?
文档说标识符语法,即表名、列名,没有选择模式的地方,所以如果你在做schemaName.tableName,查询可能会呈现错误。
它建议改用.withSchema('schemaName')
。
但我发现.withSchema
只能在整个构建器块中的一个模式中工作。
到目前为止,我有以下临时解决方案:
不要在 speasure 查询中使用.withSchema
,在表名字符串中包含模式名称。
这违反了文件。
使用带有.withSchema
的子查询
{
let rows = await knex.withSchema("sandbox1")
.select('first_name', 'last_name', 'phone', 'site', "sites.name as sname")
.from('users')
.leftJoin(
knex.withSchema('public')
.table('sites')
.select()
.as("sites"),
"sites.id",
"users.site")
console.log(rows)
}
这种方式需要在子查询中使用.as
。
.joinRaw()
{
let queryBuilder = knex.withSchema("sandbox1")
.select('first_name', 'last_name', 'phone', 'site', "sites.name as sname")
.from('users')
.joinRaw("left join public.sites as sites ON sites.id = users.site", [])
let sql = queryBuilder.toSQL().toNative()
let rows = await queryBuilder
console.log((sql))
console.log(rows)
}
.raw()
{
let { rows ,rowCount } = await knex
.raw('SELECT users.first_name, users.last_name, users.phone, users.site, sites.name as sname FROM sandbox1.users, public.sites WHERE sites.id = users.site;');
console.log(rows)
}
使用 knex 的好处较少。
最后的力量。
为@codinggirl的答案添加更多细节:
使用joinRaw()您可以绑定参数。 它在整个查询中生成具有相同语法的查询。
{
const queryBuilder = knex.withSchema("sandbox1")
.select('first_name', 'last_name', 'phone', 'site', "sites.name as sname")
.from('users')
.joinRaw("left join ?? ON ?? = ??", ["public.sites", "sites.id", "users.site"])
const sql = queryBuilder.toString()
console.log(sql)
}
注意:位置绑定? 被解释为值和?? 被解释为标识符。
在 PG 上绑定的输出:
从“sandbox1”中选择“first_name”、“last_name”、“phone”、“site”、“sites”。“name”作为“sname”。“users”离开加入“public”。“sites”在“sites”上。 “id”=“用户”。“站点”
输出与 MSSQL 上的绑定:
选择 [first_name], [last_name], [phone], [site], [sites].[name] as [sname] from [sandbox1].[users] left join [public].[sites] ON [sites]。 [id] = [用户].[站点]
同时,如果没有绑定,它总是会生成:
从“sandbox1”中选择“first_name”、“last_name”、“phone”、“site”、“sites”。“name”作为“sname”。“users”离开加入 public.sites ON sites.id = users.site
最有用的评论
文档说标识符语法,即表名、列名,没有选择模式的地方,所以如果你在做schemaName.tableName,查询可能会呈现错误。
它建议改用
.withSchema('schemaName')
。但我发现
.withSchema
只能在整个构建器块中的一个模式中工作。到目前为止,我有以下临时解决方案:
不要在 speasure 查询中使用
.withSchema
,在表名字符串中包含模式名称。这违反了文件。
使用带有
.withSchema
的子查询这种方式需要在子查询中使用
.as
。.joinRaw()
.raw()
使用 knex 的好处较少。
最后的力量。