【问题标题】:Select only tables where a column contains a certain numeric value仅选择列包含特定数值的表
【发布时间】:2012-03-10 05:34:20
【问题描述】:

是否可以仅选择列 (AD_CLIENT_ID) 包含特定数值 (1000000) 的表?

我有 850 个表可供选择,每个表都有这一列,但并非所有列都包含 1000000。

【问题讨论】:

  • 我不认为它有效。(我的意思是,850 个表?)你应该思考并重新组织你的数据库结构和逻辑。
  • 请解释为什么你(认为你)需要 850 张桌子。
  • 欢迎来到 Stackoverflow!这里习惯于直奔问题。没有个人介绍,没有手续,没有签名——你的名字和头像无论如何都会出现在你的帖子下。但是你的问题的细节很重要。就像为什么您的数据库中有 850 个表一样。数据库设计可能会有所改进。

标签: sql postgresql database-design plpgsql


【解决方案1】:

嗯..

  • 强烈重新考虑您的设计。
  • 查看一个巨大的 UNION 结构 在所有表中,然后查询 WHERE AD_CLIENT_ID = 100000

【讨论】:

  • 嗨兰迪,使用以下语句,我能够检索所有具有列 AD_CLIENT_ID 的表。如何添加 AD_CLIENT_ID = 100000 的条件? SELECT DISTINCT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME IN ('columnA','ColumnB') AND TABLE_SCHEMA='YourDatabase';
  • 你不能同时做这两个。您的查询可用作游标,而游标又可用于为所有表编写 sql 语句...您可以动态运行它,也可以将其保存到脚本中以创建视图。
【解决方案2】:

您可以使用执行动态 SQL 的 plpgsql 函数获取表列表,循环遍历目录中的结果。考虑以下演示,在 PostgreSQL 9.1 上进行了测试,但至少应该适用于 8.4 或更早版本:

CREATE OR REPLACE FUNCTION f_tbl_with_value(numeric)
  RETURNS SETOF text AS
$BODY$
DECLARE
    _tbl text;
BEGIN

FOR _tbl IN
    SELECT DISTINCT quote_ident(n.nspname) || '.' || quote_ident(c.relname)
    FROM   pg_catalog.pg_attribute a
    JOIN   pg_catalog.pg_class c ON c.oid = a.attrelid
    JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
    WHERE  a.attname = 'ad_client_id'
    AND    a.attisdropped = FALSE -- column hasn't been dropped
    AND    n.nspname = 'myschema' -- search only this schema
    AND    c.relkind = 'r'  -- only real tables
LOOP    
    RETURN QUERY EXECUTE '
    SELECT ''' || _tbl || '''::text
    WHERE  EXISTS (
        SELECT *
        FROM   ' || _tbl || '
        WHERE  ad_client_id = $1
        )'
    USING $1;
END LOOP;

END;
$BODY$
  LANGUAGE plpgsql;

呼叫:

SELECT * FROM x.f_tbl_with_value(100000)

要点

  • 结果是一个表名列表,其中存在ad_client_id 列并且在至少一行中包含参数值。

  • 我使用 PostgreSQL 目录。您可以对 SQL 标准信息架构执行相同的操作,就像您在评论中演示的那样。但这要慢得多,并且仅在您想保持代码可移植性时才有用。由于这个 plpgsql 函数无论如何都不能移植到其他数据库系统,所以我使用更快的 PostgreSQL 目录表。

  • 请注意我如何使用普通 SQL 来检索表名,但使用dynamic SQL 来查询它们。

  • 请注意我如何在架构和表名上使用 quote_ident() 来防止 SQL 注入并在需要时自动保留混合大小写标识符。

  • 我使用小写字符串'ad_client_id' 作为列名。或者你真的需要大写,因为你在创建它时双引号"AD_CLIENT_ID"? (我通常建议只使用小写标识符。More about that in the manual.

【讨论】:

    猜你喜欢
    • 2021-09-15
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 2014-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-23
    相关资源
    最近更新 更多