Olá,
Como podemos implementar a junção de tabelas em dois esquemas diferentes, mas no mesmo banco de dados.
Tecnicamente, os esquemas são apenas separação lógica de tabelas dentro do mesmo banco de dados, portanto, ao escrever uma consulta SQL, tudo o que precisamos é prefixá-los com o nome do esquema.
Por exemplo,
select *
from user_schema.users as users
inner join account_schema.accounts as accounts
on users.users.id = accounts.user_id
Eu provavelmente poderia escrever abaixo de kenx.js. Isso parece bom?
knex.from('user_schema.users as users').innerJoin('account_schema.accounts as accounts',
'users.id', 'accounts.user_id')
Mas então eu vi. withSchema
opção com knex.js Qual é a vantagem de usar essa opção em vez de prefixar o nome da tabela com o esquema. Como posso usar a opção .withSchema
para juntar tabelas de dois esquemas diferentes?
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`
alguma solução para este?
O documento diz Identifier Syntax, ou seja, nome da tabela, nome da coluna, não tem lugar para selecionar o esquema, portanto, se você estiver fazendo schemaName.tableName, a consulta pode ser renderizada incorretamente.
Sugeriu usar .withSchema('schemaName')
em vez disso.
Mas descobri que .withSchema
só funciona em um esquema em todo o bloco do construtor.
Até agora, tenho as seguintes sollutins temporárias:
Não use .withSchema
na consulta de referência, inclua o nome do esquema na string do nome da tabela.
Isso contra o documento.
Use subconsulta com .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)
}
Dessa forma, é necessário usar .as
na subconsulta.
.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)
}
Isso tem menos benefícios para usar knex.
O poder definitivo.
Adicionando mais um detalhe à resposta de @codinggirl :
Usando joinRaw() você pode vincular os parâmetros. O que gera uma consulta com uma sintaxe idêntica em toda a consulta.
{
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)
}
Nota: Ligações posicionais ? são interpretados como valores e ?? são interpretados como identificadores.
Saída com ligações no PG:
selecione "first_name", "last_name", "phone", "site", "sites".."name" como "sname" de "sandbox1".."users" left join "public".."sites" ON "sites". "id" = "usuários".."site"
Saída com ligações no MSSQL:
selecione [first_name], [last_name], [phone], [site], [sites].[name] como [sname] de [sandbox1].[users] left join [public].[sites] ON [sites]. [id] = [usuários].[site]
Enquanto isso, sem vinculação, sempre geraria:
selecione "first_name", "last_name", "phone", "site", "sites"."name" como "sname" de "sandbox1".."users" left join public.sites ON sites.id = users.site
Comentários muito úteis
O documento diz Identifier Syntax, ou seja, nome da tabela, nome da coluna, não tem lugar para selecionar o esquema, portanto, se você estiver fazendo schemaName.tableName, a consulta pode ser renderizada incorretamente.
Sugeriu usar
.withSchema('schemaName')
em vez disso.Mas descobri que
.withSchema
só funciona em um esquema em todo o bloco do construtor.Até agora, tenho as seguintes sollutins temporárias:
Não use
.withSchema
na consulta de referência, inclua o nome do esquema na string do nome da tabela.Isso contra o documento.
Use subconsulta com
.withSchema
Dessa forma, é necessário usar
.as
na subconsulta..joinRaw()
.raw()
Isso tem menos benefícios para usar knex.
O poder definitivo.