简体   繁体   English

如何查询多个SQL表以查找特定的键值对?

[英]how do I query multiple SQL tables for a specific key-value pair?

Situation: A PHP application with multiple installable modules creates a new table in database for each, in the style of mod_A, mod_B, mod_C etc. Each has the column section_id. 情况:具有多个可安装模块的PHP应用程序会在数据库中为每个表创建一个新表,格式为mod_A,mod_B,mod_C等。每个表都有section_id列。

Now, I am looking for all entries for a specific section_id, and I'm hoping there's another way besides "Select * from mod_a, mod_b, mod_c ... mod_xyzzy where section_id=value"... or even worse, using a separate query for each module. 现在,我正在寻找特定section_id的所有条目,我希望除了“从mod_a,mod_b,mod_c ... mod_xyzzy中的select *,其中section_id = value的内容中选择*”以外,还有另一种方法,甚至使用单独的方法查询每个模块。

What about? 关于什么?

SELECT * FROM mod_a WHERE section_id=value
UNION ALL
SELECT * FROM mod_b WHERE section_id=value
UNION ALL
SELECT * FROM mod_c WHERE section_id=value

If the tables are changing over time, you can inline code gen your solution in an SP (pseudo code - you'll have to fill in): 如果表随时间变化,则可以在SP中内联代码生成解决方案(伪代码-您必须填写):

SET @sql = ''

DECLARE CURSOR FOR
SELECT t.[name] AS TABLE_NAME
FROM sys.tables t
WHERE t.[name] LIKE 'SOME_PATTERN_TO_IDENTIFY_THE_TABLES'

-- or this - 或这个

DECLARE CURSOR FOR
SELECT t.[name] AS TABLE_NAME
FROM TABLE_OF_TABLES_TO_SEACRH t

START LOOP

IF @sql <> '' SET @sql = @sql + 'UNION ALL '
SET @sql = 'SELECT * FROM [' + @TABLE_NAME + '] WHERE section_id=value '

END LOOP

EXEC(@sql)

I've used this technique occasionally, when there just isn't any obvious way to make it future-proof without dynamic SQL. 当没有动态SQL时,没有什么明显的方法可以使它适应未来的情况时,我偶尔会使用这种技术。

Note: In your loop, you can use the COALESCE/NULL propagation trick and leave the string as NULL before the loop, but it's not as clear if you are unfamiliar with the idiom: 注意:在循环中,您可以使用COALESCE / NULL传播技巧,并在循环之前将字符串保留为NULL,但是如果您不熟悉该惯用语,则不清楚:

SET @sql = COALESCE(@sql + ' UNION ALL ', '')
    + 'SELECT * FROM [' + @TABLE_NAME + '] WHERE section_id=value '

I have two suggestions. 我有两个建议。

  1. Perhaps you need to consolidate all your tables. 也许您需要合并所有表。 If they all contain the same structure, then why not have one "master" module table, that just adds one new column identifying the module ("A", "B", "C", ....) 如果它们都包含相同的结构,那么为什么不拥有一个“主”模块表,只添加一个新列来标识模块(“ A”,“ B”,“ C”,...)。

    If your module tables are mostly the same, but you have a few columns that are different, you might still be able to consolidate all the common information into one table, and keep smaller module-specific tables with those differences. 如果您的模块表基本相同,但是有几列不同,则您仍然可以将所有公共信息合并到一个表中,并保留具有这些差异的较小的模块特定表。 Then you would just need to do a join on them. 然后,您只需要对它们进行联接。

    This suggestion assumes that your query on the column section_id you mention is super-critical to look up quickly. 此建议假定您对您提到的section_id列的查询非常关键,因此无法快速查找。 With one query you get all the common information, and with a second you would get any specific information if you needed it. 通过一个查询,您可以获得所有常用信息,而在第二查询中,您将获得所需的任何特定信息。 (And you might not -- for instance if you were trying to validate the existense of the section, then finding it in the common table would be enough) (而且您可能没有,例如,如果您尝试验证该节的exenseense,那么在公共表中找到它就足够了)

  2. Alternatively you can add another table that maps section_id's to the modules that they are in. 或者,您可以添加另一个表,将table_id映射到它们所在的模块。

    \nsection_id | section_id | module \n-----------+------- ----------- + -------\n      1 | 1 | A 一种\n      2 | 2 | B \n      3 | 3 | A 一种\n     ... | ... | ... ...\n

    This does mean though that you have to run two queries, one against this mapping table, and another against the module table to pull out any useful data. 这确实意味着您必须运行两个查询,一个查询针对此映射表,另一个查询针对模块表,以提取任何有用的数据。

    You can extend this table with other columns and indices on those columns if you need to look up other columns that are common to all modules. 如果需要查找所有模块共有的其他列,则可以使用其他列和这些列的索引来扩展此表。

    This method has the definite disadvanage that the data is duplicated. 此方法有一定的缺点,即数据是重复的。

I was going to suggest the same think as borjab. 我打算提出与borjab相同的想法。 The only problem with that is that you will have to update all of these queries if you add another table. 唯一的问题是,如果添加另一个表,则必须更新所有这些查询。 The only other option I see is a stored procedure. 我看到的唯一其他选择是存储过程。

I did think of another option here, or at least an easier way to present this. 我确实在这里想到了另一种选择,或者至少是一种更简单的方式来表达这一点。 You can also use a view to these multiple tables to make them appear as one, and then your query would look cleaner, be easier to understand and you wouldn't have to rewrite a long union query when you wanted to do other queries on these multiple tables. 您还可以对这些多个表使用视图,以使它们显示为一个,然后您的查询看起来将更整洁,更易于理解,并且当您要对这些表进行其他查询时不必重写长的联合查询。多个表。

Perhaps some additional info would help, but it sounds like you have the solution already. 也许一些其他信息会有所帮助,但是听起来您已经有了解决方案。 You will have to select from all the tables with a section_id. 您将必须从所有带有section_id的表中进行选择。 You could use joins instead of a table list, joining on section_id. 您可以在section_id上使用联接而不是表列表。 For example 例如

select a.some_field, b.some_field.... 
from mod_a a
inner join mod_b b on a.section_id = b.section_id
...
where a.section_id = <parameter>

You could also package this up as a view. 您也可以将其打包为视图。 Also notice the field list instead of *, which I would recommend if you were intending to actually use *. 还要注意字段列表而不是*,如果您打算实际使用*,我会建议您这样做。

Well, there are only so many ways to aggregate information from multiple tables. 好吧,只有这么多种方法可以聚合来自多个表的信息。 You can join, like you mentioned in your example, or you can run multiple queries and union them together as in borjab's answer. 您可以像在示例中提到的那样加入,也可以运行多个查询并将其合并在一起,如borjab的答案中所述。 I don't know if some idea of creating a table that intersects all the module tables would be useful to you, but if section_id was on a table like that you'd be able to get everything from a single query. 我不知道创建一个与所有模块表相交的表的想法对您是否有用,但是如果section_id在这样的表上,您将能够从单个查询中获取所有信息。 Otherwise, I applaud your laziness, but am afraid to say, I don't see any way to make that job eaiser :) 否则,我为您的懒惰鼓掌,但恐怕要说,我看不出有什么方法可以使工作更轻松:)

SELECT * FROM (
    SELECT * FROM table1
    UNION ALL
    SELECT * FROM table2
    UNION ALL
    SELECT * FROM table3
) subQry
WHERE field=value

An option from the database side would be to create a view of the UNION ALL of the various tables. 数据库方面的一种选择是创建各种表的UNION ALL的视图。 When you add a table, you would need to add it to the view, but otherwise it would look like a single table. 添加表时,需要将其添加到视图中,否则它将看起来像一个表。

CREATE VIEW modules AS (
    SELECT * FROM mod_A
    UNION ALL 
    SELECT * FROM mod_B
    UNION ALL 
    SELECT * FROM mod_C
);

select * from modules where section_id=value;

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

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