como faço para consulta tabelas SQL múltiplas para um par valor-chave específica?

StackOverflow https://stackoverflow.com/questions/104230

  •  01-07-2019
  •  | 
  •  

Pergunta

Situação: Uma aplicação PHP com múltiplos módulos instaláveis ??cria uma nova tabela na base de dados para cada um, no estilo de mod_A, mod_B, mod_C etc. Cada um tem o section_id coluna

.

Agora, eu estou olhando para todas as entradas para a SECTION_ID específico, e eu estou esperando há outra maneira além de "Select * from mod_a, mod_b, mod_c ... mod_xyzzy onde SECTION_ID = valor" ... ou ainda pior, usando uma consulta separada para cada módulo.

Foi útil?

Solução

Se as tabelas estão mudando ao longo do tempo, você pode código embutido gen sua solução em uma SP (código pseudo - você terá que preencher):

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'

- ou esta

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)

Eu usei esta técnica, ocasionalmente, quando simplesmente não há qualquer maneira óbvia para torná-lo à prova de futuro, sem SQL dinâmica.

Nota: No seu loop, você pode usar o truque de propagação COALESCE / NULL e deixar a cadeia como NULL antes do loop, mas não é tão claro, se você não estiver familiarizado com o idioma:

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

Outras dicas

Sobre o quê?

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

Eu tenho duas sugestões.

  1. Talvez você precisa para consolidar todas as suas tabelas. Se todos eles contêm a mesma estrutura, então por que não ter um "mestre" mesa módulo, que acrescenta uma nova coluna de identificação do módulo ( "A", "B", "C", ....)

    Se suas tabelas de módulos são basicamente o mesmo, mas você tem algumas colunas que são diferentes, você ainda pode ser capaz de consolidar todas as informações comuns em uma mesa, e manter menores tabelas específicas do módulo com essas diferenças. Então você só precisa fazer uma junção neles.

    Esta sugestão assume que sua consulta na coluna section_id que você menciona é super-crítica para olhar para cima rapidamente. Com uma consulta de obter todas as informações comuns, e com um segundo que se obtém qualquer informação específica se necessária. (E você não pode - por exemplo, se você estava tentando validar o existense da seção, em seguida, encontrando-o na tabela comum seria suficiente)

  2. Como alternativa, você pode adicionar uma outra tabela que mapeia de SECTION_ID aos módulos que eles estão em.

    section_id | module
    -----------+-------
          1    |  A
          2    |  B
          3    |  A
         ...   | ...
    

    Este faz que significa que você tem que executar duas consultas, uma contra esta tabela de mapeamento, e outro contra a mesa de módulo para retirar quaisquer dados úteis.

    Você pode estender essa tabela com outras colunas e índices nessas colunas, se você precisa olhar para cima outras colunas que são comuns a todos os módulos.

    Este método tem a disadvanage definitiva de que os dados são duplicados.

Talvez alguma informação adicional ajudaria, mas parece que você tem a solução já. Você terá que escolher entre todas as tabelas com uma SECTION_ID. Você poderia usar se junta em vez de uma lista de tabela, juntando-se em SECTION_ID. Por exemplo

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>

Você também pode empacotar isso como uma visão. Além disso, observe a lista de campos em vez de *, que eu recomendaria se você estivesse com a intenção de realmente usar *.

Bem, só há tantas maneiras de agregar informações de várias tabelas. Você pode participar, como você mencionou no seu exemplo, ou você pode executar várias consultas e união los juntos como na resposta de borjab. Eu não sei se alguma idéia de criar uma tabela que cruza todas as tabelas de módulos seria útil para você, mas se SECTION_ID estava em uma mesa como que você seria capaz de conseguir tudo de uma única consulta. Caso contrário, eu aplaudo a sua preguiça, mas tenho medo de dizer, eu não vejo nenhuma maneira de fazer que eaiser trabalho:)

Eu ia sugerir a mesma pensar como borjab. O único problema com isso é que você terá que atualizar todas estas consultas se você adicionar outra tabela. A única outra opção que vejo é um procedimento armazenado.

Eu achava que de outra opção aqui, ou pelo menos uma maneira mais fácil de apresentar este. Você também pode usar a fim de estas várias tabelas para torná-los aparecer como um, e, em seguida, sua consulta seria mais limpo, mais fácil de entender e você não teria que reescrever uma consulta de união muito tempo quando você queria fazer outras consultas sobre estes várias tabelas.

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

Uma opção do lado do banco de dados seria a criação de uma vista do UNION ALL das várias tabelas. Quando você adiciona uma tabela, você precisa adicioná-lo à vista, mas caso contrário ele seria parecido com uma única tabela.

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;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top