Pregunta

Situación:Una aplicación PHP con múltiples módulos instalables crea una nueva tabla en la base de datos para cada uno, al estilo mod_A, mod_B, mod_C, etc.Cada uno tiene la columna sección_id.

Ahora, estoy buscando todas las entradas para una sección_id específica, y espero que haya otra forma además de "Seleccionar * de mod_a, mod_b, mod_c...mod_xyzzy donde sección_id=valor"...o peor aún, usar una consulta separada para cada módulo.

¿Fue útil?

Solución

Si las tablas cambian con el tiempo, puede generar un código en línea para generar su solución en un SP (pseudocódigo; deberá completarlo):

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'

-- o esto

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)

He usado esta técnica ocasionalmente, cuando simplemente no hay ninguna forma obvia de prepararla para el futuro sin SQL dinámico.

Nota:En tu bucle, puedes usar el truco de propagación COALESCE/NULL y dejar la cadena como NULL antes del bucle, pero no está tan claro si no estás familiarizado con el modismo:

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

Otros consejos

¿Qué pasa?

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

Tengo dos sugerencias.

  1. Quizás necesites consolidar todas tus tablas.Si todos contienen la misma estructura, entonces ¿por qué no tener una tabla de módulo "maestra", que simplemente agrega una nueva columna que identifica el módulo ("A", "B", "C", ....)

    Si las tablas de sus módulos son en su mayoría iguales, pero tiene algunas columnas que son diferentes, es posible que aún pueda consolidar toda la información común en una tabla y mantener tablas más pequeñas específicas de los módulos con esas diferencias.Entonces sólo tendrías que unirte a ellos.

    Esta sugerencia supone que su consulta en la columna section_id que menciona es muy crítica para buscarla rápidamente.Con una consulta obtienes toda la información común y con una segunda obtienes información específica si la necesitas.(Y es posible que no; por ejemplo, si estuviera intentando validar la existencia de la sección, entonces sería suficiente encontrarla en la tabla común)

  2. Alternativamente, puede agregar otra tabla que asigne los ID de sección a los módulos en los que se encuentran.

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

    Sin embargo, esto significa que debe ejecutar dos consultas, una en esta tabla de mapeo y otra en la tabla de módulos para extraer datos útiles.

    Puede ampliar esta tabla con otras columnas e índices en esas columnas si necesita buscar otras columnas que sean comunes a todos los módulos.

    Este método tiene claramente la desventaja de que los datos se duplican.

Quizás alguna información adicional ayudaría, pero parece que ya tienes la solución.Tendrás que seleccionar entre todas las tablas con un ID de sección.Podrías usar uniones en lugar de una lista de tablas, uniéndote en sección_id.Por ejemplo

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>

También puedes empaquetar esto como una vista.Observe también la lista de campos en lugar de *, lo cual recomendaría si tuviera la intención de utilizar *.

Bueno, hay muchas formas de agregar información de varias tablas.Puede unirse, como mencionó en su ejemplo, o puede ejecutar varias consultas y unirlas como en la respuesta de Borjab.No sé si le resultaría útil la idea de crear una tabla que cruce todas las tablas de módulos, pero si sección_id estuviera en una tabla como esa, podría obtener todo desde una sola consulta.Por lo demás, aplaudo tu pereza, pero temo decir que no veo ninguna manera de facilitar ese trabajo :)

Iba a sugerir lo mismo que Borjab.El único problema con esto es que tendrá que actualizar todas estas consultas si agrega otra tabla.La única otra opción que veo es un procedimiento almacenado.

Pensé en otra opción aquí, o al menos en una forma más fácil de presentar esto.También puede usar una vista de estas múltiples tablas para que aparezcan como una sola, y luego su consulta se verá más limpia, será más fácil de entender y no tendrá que reescribir una consulta de unión larga cuando desee realizar otras consultas sobre estas. varias tablas.

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

Una opción desde el lado de la base de datos sería crear una vista de UNION TODAS las distintas tablas.Cuando agrega una tabla, deberá agregarla a la vista, pero de lo contrario se verá como una sola tabla.

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top