繁体   English   中英

在SQLAlchemy中引用表名和列名

[英]Quoting table and column names in SQLAlchemy

我有一个函数,使用此代码将触发器添加到指定的表( 此处为完整的函数代码 ):

event.listen(primary_table, 'after_create', DDL('''
    CREATE FUNCTION {primary_table_name}_validate() RETURNS TRIGGER AS $$
    DECLARE
        target RECORD;
    BEGIN
        IF (NEW.{rhs} IS NOT NULL) THEN
            SELECT {parentcol} INTO target FROM {child_table_name} WHERE {child_id_column} = NEW.{rhs};
            IF (target.{parentcol} != NEW.{lhs}) THEN
                RAISE foreign_key_violation USING MESSAGE = 'The target is not affiliated with this parent';
            END IF;
        END IF;
        RETURN NEW;
    END;
    $$ LANGUAGE plpgsql;
    CREATE TRIGGER {primary_table_name}_trigger BEFORE INSERT OR UPDATE
    ON {primary_table_name}
    FOR EACH ROW EXECUTE PROCEDURE {primary_table_name}_validate();
    '''.format(
    primary_table_name=primary_table_name,
    parentcol=parentcol,
    child_table_name=child_table_name,
    child_id_column=child_id_columns[0],
    lhs=parent_table_name + '_' + parent_id_columns[0],
    rhs=child_table_name + '_' + child_id_columns[0],
)).execute_if(dialect='postgresql'))

event.listen(primary_table, 'before_drop', DDL('''
    DROP TRIGGER {primary_table_name}_trigger ON {primary_table_name};
    DROP FUNCTION {primary_table_name}_validate();
    '''.format(primary_table_name=primary_table_name)).execute_if(dialect='postgresql'))

我不想在SQL中嵌入原始字符串,因为它会阻塞像user这样的名字(使用PostgreSQL)。 我不能使用SQLAlchemy的bindparam因为它们是表名和列名,而不是数据。 SQLAlchemy提供了一个quoted_name 和一个quote_identifier ,似乎quoted_name我的需要,但是我如何在这里使用它们呢?

为了回答我自己的问题, DDL接受一个应用于SQL语句的context字典。 这是修改后的代码:

event.listen(primary_table, 'after_create',
    DDL('''
        CREATE FUNCTION %(function)s() RETURNS TRIGGER AS $$
        DECLARE
            target RECORD;
        BEGIN
            IF (NEW.%(rhs)s IS NOT NULL) THEN
                SELECT %(parentcol)s INTO target FROM %(child_table_name)s WHERE %(child_id_column)s = NEW.%(rhs)s;
                IF (target.%(parentcol)s != NEW.%(lhs)s) THEN
                    RAISE foreign_key_violation USING MESSAGE = 'The target is not affiliated with this parent';
                END IF;
            END IF;
            RETURN NEW;
        END;
        $$ LANGUAGE plpgsql;
        CREATE TRIGGER %(trigger)s BEFORE INSERT OR UPDATE
        ON %(table)s
        FOR EACH ROW EXECUTE PROCEDURE %(function)s();
        ''',
        context={
            'table': primary_table_name,
            'function': '%s_validate' % primary_table_name,
            'trigger': '%s_trigger' % primary_table_name,
            'parentcol': parentcol,
            'child_table_name': child_table_name,
            'child_id_column': child_id_columns[0],
            'lhs': '%s_%s' % (parent_table_name, parent_id_columns[0]),
            'rhs': '%s_%s' % (child_table_name, child_id_columns[0]),
        }
    ).execute_if(dialect='postgresql')
)

event.listen(primary_table, 'before_drop',
    DDL('''
        DROP TRIGGER %(trigger)s ON %(table)s;
        DROP FUNCTION %(function)s();
        ''',
        context={
            'table': primary_table_name,
            'trigger': '%s_trigger' % primary_table_name,
            'function': '%s_validate' % primary_table_name,
        }
    ).execute_if(dialect='postgresql')
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM