Hallo,
Wie können wir Tabellenverknüpfungen über zwei verschiedene Schemas hinweg, aber in derselben Datenbank implementieren?
Technisch gesehen sind Schemas nur eine logische Trennung von Tabellen innerhalb derselben Datenbank. Beim Schreiben einer SQL-Abfrage müssen wir ihnen also nur den Schemanamen voranstellen.
Beispielsweise,
select *
from user_schema.users as users
inner join account_schema.accounts as accounts
on users.users.id = accounts.user_id
Ich könnte wahrscheinlich unten kenx.js schreiben. Sieht das gut aus?
knex.from('user_schema.users as users').innerJoin('account_schema.accounts as accounts',
'users.id', 'accounts.user_id')
Aber dann sah ich. Option withSchema
mit knex.js Was ist der Vorteil bei der Verwendung dieser Option, anstatt dem Tabellennamen ein Schema voranzustellen. Wie kann ich die Option .withSchema
verwenden, um Join-Tabellen aus zwei verschiedenen Schemas zu verbinden?
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`
eine Lösung für diese?
Das Dokument sagt, dass die Identifier-Syntax, dh Tabellenname, Spaltenname, keinen Platz zum Auswählen des Schemas hat. Wenn Sie also schemaName.tableName ausführen, wird die Abfrage möglicherweise falsch gerendert.
Es wurde vorgeschlagen, stattdessen .withSchema('schemaName')
zu verwenden.
Aber ich habe festgestellt, dass .withSchema
im gesamten Builder-Block nur in einem Schema funktioniert.
Bisher habe ich folgende temporäre Sollutins:
Verwenden Sie .withSchema
überhaupt nicht in Speasure-Abfragen, fügen Sie den Schemanamen in die Zeichenfolge des Tabellennamens ein.
Dies gegen das Dokument.
Verwenden Sie die Unterabfrage mit .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)
}
Auf diese Weise müssen Sie .as
in der Unterabfrage verwenden.
.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)
}
Dies hat weniger Vorteile bei der Verwendung von Knex.
Die letzte Kraft.
Fügen Sie der Antwort von @codinggirl ein weiteres Detail hinzu:
Mit joinRaw() können Sie die Parameter binden. Dadurch wird eine Abfrage mit einer identischen Syntax für die gesamte Abfrage generiert.
{
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)
}
Hinweis: Positionsbindungen ? werden als Werte interpretiert und ?? werden als Bezeichner interpretiert.
Ausgabe mit Bindings auf PG:
Wählen Sie „Vorname“, „Nachname“, „Telefon“, „Site“, „Sites“. „Name“ als „Sname“ aus „Sandbox1“. "id" = "users".."site"
Ausgabe mit Bindungen auf MSSQL:
Wählen Sie [Vorname], [Nachname], [Telefon], [Site], [Sites].[Name] als [Sname] aus [Sandbox1].[Benutzer] verließen Join [public].[Sites] ON [Sites]. [id] = [Benutzer].[Website]
In der Zwischenzeit würde es ohne Bindung immer Folgendes generieren:
Wählen Sie „Vorname“, „Nachname“, „Telefon“, „Site“, „Sites“. „Name“ als „Sname“ aus „Sandbox1“. „Benutzer“ links Join public.sites ON sites.id = users.site
Hilfreichster Kommentar
Das Dokument sagt, dass die Identifier-Syntax, dh Tabellenname, Spaltenname, keinen Platz zum Auswählen des Schemas hat. Wenn Sie also schemaName.tableName ausführen, wird die Abfrage möglicherweise falsch gerendert.
Es wurde vorgeschlagen, stattdessen
.withSchema('schemaName')
zu verwenden.Aber ich habe festgestellt, dass
.withSchema
im gesamten Builder-Block nur in einem Schema funktioniert.Bisher habe ich folgende temporäre Sollutins:
Verwenden Sie
.withSchema
überhaupt nicht in Speasure-Abfragen, fügen Sie den Schemanamen in die Zeichenfolge des Tabellennamens ein.Dies gegen das Dokument.
Verwenden Sie die Unterabfrage mit
.withSchema
Auf diese Weise müssen Sie
.as
in der Unterabfrage verwenden..joinRaw()
.raw()
Dies hat weniger Vorteile bei der Verwendung von Knex.
Die letzte Kraft.