Hello,
How can we implement table join across two different schemas but the same database.
Technically schemas are just logical separation of tables within the same database so while writing a SQL query all we need to is prefix them with schema name.
For example,
select *
from user_schema.users as users
inner join account_schema.accounts as accounts
on users.users.id = accounts.user_id
I could probably write below kenx.js. Does that look good ?
knex.from('user_schema.users as users').innerJoin('account_schema.accounts as accounts',
'users.id', 'accounts.user_id')
But then i saw .withSchema
option with knex.js What is the advantage of using that option instead of prefixing the table name with schema. How can I use .withSchema
option to join join tables from two different schemas ?
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`
any solution for this one?
The document says Identifier Syntax, ie, table name, column name, has no place for selecting schema, so if you are doing schemaName.tableName, query might be rendered wrong.
It suggested use .withSchema('schemaName')
instead.
But I found .withSchema
only work in one schema all over the builder block.
As so far, I have the following temporary sollutins:
Do not use .withSchema
at all in speasure query, include schema name in table name string.
This against the document.
Use sub-query with .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)
}
This way need use .as
in sub query.
.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)
}
This has less benifits to use knex.
The final power.
Adding one more detail to @codinggirl 's answer:
Using joinRaw() you can bind the parameters. Which generates query with an identical syntax all over the query.
{
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)
}
Note: Positional bindings ? are interpreted as values and ?? are interpreted as identifiers.
Output with bindings on PG:
select "first_name", "last_name", "phone", "site", "sites"."name" as "sname" from "sandbox1"."users" left join "public"."sites" ON "sites"."id" = "users"."site"
Output with bindings on MSSQL:
select [first_name], [last_name], [phone], [site], [sites].[name] as [sname] from [sandbox1].[users] left join [public].[sites] ON [sites].[id] = [users].[site]
Meanwhile, without binding, it would always generate:
select "first_name", "last_name", "phone", "site", "sites"."name" as "sname" from "sandbox1"."users" left join public.sites ON sites.id = users.site
Most helpful comment
The document says Identifier Syntax, ie, table name, column name, has no place for selecting schema, so if you are doing schemaName.tableName, query might be rendered wrong.
It suggested use
.withSchema('schemaName')
instead.But I found
.withSchema
only work in one schema all over the builder block.As so far, I have the following temporary sollutins:
Do not use
.withSchema
at all in speasure query, include schema name in table name string.This against the document.
Use sub-query with
.withSchema
This way need use
.as
in sub query..joinRaw()
.raw()
This has less benifits to use knex.
The final power.