查找具有特定值

时间:2016-05-20 09:28:17

标签: sql stored-procedures firebird firebird2.5

我正在使用Firebird 2.5.0。我知道一个值,需要找到它所在的所有表,列。
我创建了程序:

CREATE OR ALTER PROCEDURE NEW_PROCEDURE (
    searching_value varchar(30))
returns (
    table_with_value varchar(100),
    column_with_value varchar(100))
as 
declare variable all_tables varchar(50);
declare variable all_columns varchar(50);
declare variable all_values varchar(50);
begin
    FOR SELECT
        r.rdb$relation_name, f.rdb$field_name
        from rdb$relation_fields f
        join rdb$relations r on f.rdb$relation_name = r.rdb$relation_name
        and r.rdb$view_blr is null 
        and (r.rdb$system_flag is null or r.rdb$system_flag = 0)
        order by 1, f.rdb$field_position INTO :all_tables, :all_columns
    DO
    BEGIN
        FOR SELECT all_columns FROM all_tables
            INTO :all_Values
        DO
        BEGIN
            IF (SEARCHING_VALUE = all_Values) THEN
            BEGIN
                table_With_Value = all_Tables;
                column_With_Value = all_Columns;
                SUSPEND;
            END
        END
    END
END^

当我运行它时,我收到错误消息:
未定义的名称。
动态SQL错误。
SQL错误代码= -204。
表未知。
ALL_TABLES。
在第21行第13栏。

因此在这个select语句“SELECT all_columns FROM all_tables”中,它没有从select语句的前一个值中获取值,而只是尝试查找表all_tables。如何解决?

1 个答案:

答案 0 :(得分:3)

问题在于all_columns被认为是列名,而all_tables是表名,而不是您的变量:

SELECT all_columns FROM all_tables

您无法在此类查询中参数化对象名称。另请注意,如果可以参数化对象名称,则必须使用:all_columns:all_tables来消除歧义。

相反,您需要创建一个动态SQL语句并使用EXECUTE STATEMENT(或更具体地:FOR EXECUTE STATEMENT)执行该语句。

在这种情况下:

FOR EXECUTE STATEMENT 'SELECT "' || all_columns || '" FROM "' || all_tables || '"'
    INTO :all_values
DO
BEGIN
    /* .... */
END

我引用了对象名称来说明区分大小写的列和表名(或无引号无效的标识符)。如果从Firebird元数据表之外的其他源获取值,那么构造这样的查询可能会让您对SQL注入开放。