查找具有特定值的表和列

4

我正在使用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
我没有检查过这个语句,但是你不能从all_tables中读取数据,因为Firebird会搜索名为all_tables的表。请使用execute statement来获取数据。http://www.ibexpert.net/ibe/index.php?n=Doc.EXECUTESTATEMENTFB2 - MBDev
你不能这样参数化表名,你需要使用带有动态构建查询的 EXECUTE STATEMENT - Mark Rotteveel
1个回答

4
问题在于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注入的风险。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接