Ich möchte eine Migrationszeichenfolge schreiben, um dem Aufzählungsspaltentyp eine neue Zeichenfolge hinzuzufügen. Ich versuche, gamma
zur Spalte service
hinzuzufügen.
Ich habe es mit diesem Code unten versucht. Dies kollidiert, weil die Tabelle und die Spalte bereits vorhanden sind.
const table = 'user_associations'
export function up (knex, Promise) {
return knex.schema.table(table, function (table) {
table.enu('service', ['alpha', 'beta', 'gamma']).notNullable()
})
}
export function down (knex, Promise) {
return knex.schema.table(table, function (table) {
table.enu('service', ['alpha', 'beta']).notNullable()
})
}
Wie kann man die alter
API verwenden?
Aufzählungen werden derzeit mit Prüfbeschränkungen erstellt und .alter()
hat keine spezielle Behandlung für sie ...
Ein Problem ist, dass .alter()
den ursprünglichen Typ der Spalte nicht kennt und daher nicht weiß, ob es die alte Überprüfungsbeschränkung von enum löschen soll.
Soweit ich weiß, kann man die erlaubten Enum-Werte derzeit nur mit knex.raw
ändern, indem man alte ablegt und neue Check-Constraints erstellt...
Ich denke, es könnte von einigen drop old constraint if exist
implementiert werden und dann eine neue erstellen, wenn der geänderte Typ der Spalte enum ist.
Ich würde mich freuen, wenn diese Funktion implementiert wird.
@elhigu Ich habe eine benutzerdefinierte Enum-Abfrage geschrieben, damit ich Postgres-Enums verwenden kann, aber in der Postgres-Community gibt es einige Diskussionen über Prüfbedingungen vs
Nur für alle, die wissen wollen, wie der Code _might_ in Postgres 9 aussieht
const formatAlterTableEnumSql = (
tableName,
columnName,
enums,
) => {
const constraintName = `${tableName}_${columnName}_check`;
return [
`ALTER TABLE ${tableName} DROP CONSTRAINT IF EXISTS ${constraintName};`,
`ALTER TABLE ${tableName} ADD CONSTRAINT ${constraintName} CHECK (${columnName} = ANY (ARRAY['${enums.join(
"'::text, '"
)}'::text]));`,
].join('\n');
};
exports.up = async function up(knex) {
await knex.raw(
formatAlterTableEnumSql('myTableName', 'myColumnName', [
'enum1',
'enum2',
'enum3',
])
);
};
exports.down = async function down(knex) {
await knex.raw(
formatAlterTableEnumSql('myTableName', 'myColumnName', [
'enum1',
'enum2',
])
);
};
@holloway Danke für das Migrationscodebeispiel. Genau das, was ich gesucht habe. Ich stoße jedoch auf ein Problem. 'myColumnName' gibt beim Migrieren einen Fehler aus. Die Meldung sagt "Spalte 'mycolumnname' existiert nicht". Beachten Sie, dass das camelCase jetzt fehlt. Irgendwelche Ideen, wie man das umgehen kann?
@Jordan24 Kannst du deinen Code teilen?
'use strict';
const formatAlterTableEnumSql = (tableName, columnName, enums) => {
const constraintName = `${tableName}_${columnName}_check`;
return [
`ALTER TABLE ${tableName} DROP CONSTRAINT IF EXISTS ${constraintName};`,
`ALTER TABLE ${tableName} ADD CONSTRAINT ${constraintName} CHECK (${columnName} = ANY (ARRAY['${enums.join(
`'::text, '`
)}'::text]));`
].join('\n');
};
exports.up = async function up(knex) {
await knex.raw(
formatAlterTableEnumSql('item_messages', 'sentMethod', [
'Web App', 'Email', 'Text Message', 'Log Conversation'
])
);
};
exports.down = async function down(knex) {
await knex.raw(
formatAlterTableEnumSql('item_messages', 'sentMethod', [
'Web App', 'Email', 'Text Message'
])
);
};
Wenn ich den Spaltennamen in doppelte Anführungszeichen einschließe, erhalte ich einen Syntaxfehler, da die einfachen Anführungszeichen nicht im Rohcode entfernt werden.
Ich denke, ich könnte die Funktion fallen lassen und den Rohcode einfach zweimal schreiben.
@Jordan24 Ohne die Anführungszeichen faltet PostgreSQL alle Bezeichner in Kleinbuchstaben um.
Alles außer der 'Enum' hart codiert, um es zu umgehen. Danke für den Tipp @kibertoad!
Hilfreichster Kommentar
Nur für alle, die wissen wollen, wie der Code _might_ in Postgres 9 aussieht