Knex: Junte duas tabelas em dois esquemas diferentes (um banco de dados)

Criado em 23 jul. 2016  ·  3Comentários  ·  Fonte: knex/knex

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`

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

    {
        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.

  • Usar .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)
    }
  • Usar .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.

  • Use outra biblioteca ou ORMs ou drivers.

O poder definitivo.

Todos 3 comentários

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.

  • Usar .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)
    }
  • Usar .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.

  • Use outra biblioteca ou ORMs ou drivers.

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

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

saurabhghewari picture saurabhghewari  ·  3Comentários

arconus picture arconus  ·  3Comentários

koskimas picture koskimas  ·  3Comentários

rarkins picture rarkins  ·  3Comentários

ghost picture ghost  ·  3Comentários