Usando vistas para crear subconjuntos de datos
Posted by Miguel Egea | Posted in Relacional | Posted on 16-01-2010
0
La verdad es que he usado esta técinca bastante, lo que hago es crear vistas, en una base de datos que apunten a las tablas o vistas originales en la otra base de datos. De esta forma no se duplica el espacio, y además no se penaliza (apenas) el rendimiento, en principio la única operación adicional que hace el motor frente a que estén en la misma base de datos es comprobar que el usuario tenga permisos en la otra base de datos. En resumen, no es malo crear una vista en una base de datos apuntando a otra en el mismo server, las operaciones CRUD (Inserción, lectura, actualización y borrado) segurian funcionando todas como si de una tabla se tratase.
Sin embargo si quieres crear un gran número de vistas, la cosa puede ser tediosa. Si sé que por ejemplo voy a crear vistas para todas las tablas de un esquema, o para todas las que cumplen ciertos patrones, puedo utilizar otra técnica que exploto de vez en cuando, crear una consulta que me devuelva las consultas a ejecutar, para despues de esto copiar y pegar.
Si las operaciones a hacer son CRUD, no hay problema separandolas con ; todo funciona perfectamente, sin embargo si las operaciones a realizar son operaciones de definición de objetos (sentencias DDL), entonces hay que sepaararlas por GO para ejecutarlas en el entorno, o bien, hay que ejecutarlas una a una, esto, tampoco es algo que yo desee. ¿como hago para añadir los GO?. Las técnicas que uso habitualmente son dos una añadir al final de la sentencia el caracter 13 y el caracter 10 . Algo así
select 'select 1 ' +char(10) +CHAR(13) + 'go' |
Sin embargo este código no funciona en el modo Grid, habitual de management estudio, si copiamos desde el grid el código y lo pegamos, nos aparecerá en una sola línea y no en dos, que es lo que buscamo,s así pues hemos de pasara a modo texto (pulsando CTRL+to bien en el menú Query->Results To->Text. La verdad es que queda algo “chapuza” esta alternativa.
¿alguna otra solución? Pues lo que tendríamos que hacer es además de construir la sentencia, añadir tantos “GO” como sentencias haya… eso es sencillo, si la primera linea es :
select 'CREATE VIEW ' + TABLE_SCHEMA+'.['+TABLE_NAME + '] AS select * from vdnav60.'+table_schema+'.['+table_name+'];' from information_Schema.tables where table_name like '%patron%' |
Lo que hemos de hacer es un select, pero esta vez solo con el literal “GO” del mismo origen, de esta forma tendremos el mismo número de “go”. Sería algo así
select 'GO' from information_Schema.tables where table_name like '%patron%' |
El problema aquí viene por dos partes, la primera, las dos sentencias no son una sola, que es lo que yo necesito, (sin embargo ambas solo devuelven una columna, que es un literal con lo que sirve como código). Esto podemos solucionarlo usando una cláusula UNION ALL (al ser la estrutura devuelta igual).
Pero esto aún encierra un problema adicional, que es que no vienen en el orden adecuado, para ordenar algo podemos usar la cláusula order by, pero no tenemos ningún campo que nos sirva para hacer ese entrelazado (o al menos no podemos suponer que lo tenemos), es por ello que yo uso este otro script.
select 'CREATE VIEW ' + TABLE_SCHEMA+'.['+TABLE_NAME + '] AS select * from vdnav60.'+table_schema+'.['+table_name+'];' from information_Schema.tables where table_name like '%patron%' union all select row_number() over( order by table_name), 'go' from vdnav60.information_Schema.tables where table_name like '%patron%' |
Las cláusulas Row_number() nos van a devolver el número de fila según los criterios que usemos (partition by y order by), y luego como las dos tablas debieran devolver lo mismo, el resultado es que ordenando por ese número de fila, obtendremos la consulta perfectamente compuesta , como puede verse en la imagen
Disfrutad el código

