Reindexar una base de datos Express por linea de comandos

Posted by Miguel Egea | Posted in Basicos Newsgroup, Relacional | Posted on 03-12-2011

0

graba el contenido del código T-SQL en un fichero que se llame reindexa.SQL  El código está sacado de los libros en pantalla de la ayuda del producto.

Una vez que tengas ese fichero (llamado en mi caso c:\reindexa.sql ejecuta desde la linea de comandos esta línea

c:\>sqlcmd -S localhost -E -d tubasededatos -i c:\reindex.sql

con esto se ejecutará el script que en principio debe reindexar toda tu base de datos. recuerda cambiar en la ejecutcion de arriba donde pone tubasededatos por el nombre de tu base de datos.

 

SET NOCOUNT ON;
DECLARE @objectid int;
DECLARE @indexid int;
DECLARE @partitioncount bigint;
DECLARE @schemaname nvarchar(130); 
DECLARE @objectname nvarchar(130); 
DECLARE @indexname nvarchar(130); 
DECLARE @partitionnum bigint;
DECLARE @partitions bigint;
DECLARE @frag float;
DECLARE @command nvarchar(4000); 
-- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function 
-- and convert object and index IDs to names.
SELECT
    object_id AS objectid,
    index_id AS indexid,
    partition_number AS partitionnum,
    avg_fragmentation_in_percent AS frag
INTO #work_to_do
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED')
WHERE avg_fragmentation_in_percent > 10.0 AND index_id > 0;
 
-- Declare the cursor for the list of partitions to be processed.
DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do;
 
-- Open the cursor.
OPEN partitions;
 
-- Loop through the partitions.
WHILE (1=1)
    BEGIN;
        FETCH NEXT
           FROM partitions
           INTO @objectid, @indexid, @partitionnum, @frag;
        IF @@FETCH_STATUS < 0 BREAK;
        SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(s.name)
        FROM sys.objects AS o
        JOIN sys.schemas as s ON s.schema_id = o.schema_id
        WHERE o.object_id = @objectid;
        SELECT @indexname = QUOTENAME(name)
        FROM sys.indexes
        WHERE  object_id = @objectid AND index_id = @indexid;
        SELECT @partitioncount = count (*)
        FROM sys.partitions
        WHERE object_id = @objectid AND index_id = @indexid;
 
-- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding.
        IF @frag < 30.0
            SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE';
        IF @frag >= 30.0
            SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD';
        IF @partitioncount > 1
            SET @command = @command + N' PARTITION=' + CAST(@partitionnum AS nvarchar(10));
        EXEC (@command);
        PRINT N'Executed: ' + @command;
    END;
 
-- Close and deallocate the cursor.
CLOSE partitions;
DEALLOCATE partitions;
 
-- Drop the temporary table.
DROP TABLE #work_to_do;
print "reindexación completada"
GO

 

 

Luis Franco hablando de CROSS APPLY

Posted by Miguel Egea | Posted in Noticias, Relacional | Posted on 26-09-2011

0

Cross Apply y las funciones escalares, una comparativa con el uso de funciones y como cazar lo que están haciendo realmente. Adicionalmente a lo que dice Luis, las funciones escalares no solamente pueden degradar el rendimiento cuando esas funciones a su vez llaman a tablas (en ese caso la degradacion es espectacular), sino que también lo es cuando sin ese acceso se usan como herramientas matemáticas por ejemplo (una multiplicación, operaciones con fechas o cosas así )

El motivo es que se ejecutan para cada fila, sin posibilidad de optimización y acaban sobrecargando la cpu de la máquina, y dando un mal rendimiento. Así pues.. usad la forma que dice Luis.

Por cierto, si alguno me visteis dar una charla en el developer day de ¿2009? con Fernando G. Guerrero , esto de lo que habla Luis, fué la demo que hice :) .

SQL Denali. Objeto Sequence

Posted by Miguel Egea | Posted in Relacional | Posted on 18-09-2011

1

En los grupos de noticias en castellano de SQL Server un amigo preguntaba sobre como hacer un autoincremental sobre un campo texto. lo cierto es que los campos texto no tienen autoincrementales, pero su objetivo era poder generar números muchísimo más grandes que los 18 mil millones de millones que tiene un bigint. La verdad es que todos le dijimos que si tienes en una tabla por estrecha que sea, más de 18 mil millones de millones de filas, el menor de tus problemas es el autoincremental,.. pero en cualquier caso si que me dió una idea para hablar sobre las secuencias.

Las secuencias son un objeto nuevo en SQL Server Denali, que van a ayudar a que podamos tener “más de un autonumérico” por cada una de las tablas. Este artículo será una versión corta de como se pueden solucionar este tipo de problemas. De momento, lo que se me ocurrió fué lo siguiente:

1.- Crear dos campos bigint, que sean la clave primaria de la tabla

2.- Crear un campo calculado de tipo texto que sea la concatenación de ceros y el valor del campo 1 en los 18 dígitos menos significativos y la misma operación para el campo 2

3.- Comprobar cuando el campo menos significativo supera el rango de los bigint, es decir, cuando vuelve a cero.

4.- En ese caso incrementar en uno el campo más significativo.

Creo que con esta técnica el campo calculado responde a la pregunta de nuestro amigo, aunque realmente no tenga más que una utilidad educativa y no práctica (en mi humilde opinión)

Como quiera que  un trozo de código vale más que mil palabras, aquí está la solución que propongo.

 

create sequence SecuenciaA as bigint start with 1 increment by 1 no maxvalue cycle;
create sequence Secuenciab as bigint start with 0 increment by 1 no maxvalue;
go
create table t (id1 bigint not null ,id2 bigint not null, datotest varchar(10),
campotexto as right('000000000000000000'+ cast( id2 as varchar(19)),19)+
right('000000000000000000'+ cast( id1 as varchar(19)),19) , constraint pk_t primary key (id1,id2))
go
create procedure insertaent @datotest varchar(10)
as
begin
  declare @valor1 bigint
  declare @valor2 bigint
  select @valor1=NEXT VALUE FOR SecuenciaA;
  if @valor1=0 
    select @valor2=NEXT VALUE FOR secuenciaB;
  else
   select @valor2=cast(current_value as bigint) FROM sys.sequences where name='SecuenciaB';
  insert into dbo.t values (@valor1,@valor2,@datotest);
end;
go
exec insertaent 'hola'
go
SELECT * FROM DBO.t
go
drop procedure insertaent;
drop table t;
drop sequence secuenciaA;
drop sequence secuenciaB;

SQL DMO y sus utilidades

Posted by Miguel Egea | Posted in Relacional | Posted on 13-09-2011

0

Es muy común que para desarrolladores de base de datos, incluso los más instruidos, no necesiten nunca o casi nunca usar el sistema de automatización que proveen todos los productos de microsoft. Generalmente todas las herramientas (SQL Server Management Studio es un ejemplo), no son más que interfaces que usan esa funcionalidad, que por otra parte está disponible para cualquier desarrollador con un poquito de inquietud y una necesidad de emular esos comportamientos.

Lo que os dejo hoy son dos links, uno más general sobre como usar estas funcionalidades desde scripts de windows, y un segundo enlace que va orientado a aquellos desarrolladores que quieren usar estas funcionalidades desde dentro de TSQL, no es que sea una practica a hacer en todos los casos, pero es posible que nos saque de un apuro alguna vez y eso siempre se agradece. Así que si quereis podeis seguir este enlace . En el vereis como conseguir la generación de un script de una tabla (por ejemplo) desde TSQL.

 

Heaps (montones) y tablas con índices Clustered

Posted by Miguel Egea | Posted in Noticias, Relacional | Posted on 12-09-2011

0

A veces hay que leer no solo lo que la gente usa como buenas prácticas, sino también lo que se usa como malas prácticas. En este caso Luis nos cuenta algun caso que seguramente se habrá encontrado por ahí, y su analisis sobre la fragmentación de los heaps y como alguna gente intenta evitarla, sin demasiado éxito y consumiendo recursos.

Totalmente recomendable como lectura

Artículo de BI Corner, Mitos y leyendas, defragmentacion de heaps

Administrador multiserver con SQL Server Management Studio

Posted by Miguel Egea | Posted in Relacional | Posted on 25-08-2011

3

Hace uno dias, en los foros de noticias uno de los compañeros preguntaba por herramientas de administración multiservidor. Me explico, una herramienta que cuando ejecutes un script, no solo lo ejecute en un server, sino que se encargue de que tu comando (tanto si es de manipulación de datos -DML es decir insert,update…- , como si es de definición de datos -DDL, es decir create table, etc- se ejecute en un conjunto de servidores.
Me sorprendió ver como muy poca gente conocía que esta funcionalidad la tiene SQL Server Management Studio, es cierto que no es probablemente una funcionalidad para un gran porcentaje de usuarios, pasará desapercibido, no tendrá utilidad. Sin embargo veo algunos escenarios de mucha utilidad:
  • Para aquellos que administren siquiera dos servidores pueden beneficiarse de comprobaciones de fragmentación, de índices, de seguimiento de bloqueos, y de muchas tareas administrativas.
  • Para aquellos que mantengan bases de datos idénticas en distintos servers, y que quieran asegurarse que realmente son idénticas.
Seguro que hay otro montón de escenarios útiles, pero creo que con estos dos, el lector interesado sabrá de que estoy hablando, y si no esta en estos, el que lo necesite, seguramente sea capaz de inferir que esta funcionalidad puede ser útil, también para él.
Voy a hacer la demostración y la captura de pantallas con el SQL Server Management Studio de la CTP3 de Denali, pero esto ya funciona, desde versiones anteriores (desde SQL 2008).
Lo primero que haremos será, tras abrir nuestro SQL Server Management Studio, ir al menú de Ver, y ahí elegir servidores registrados, notad como hay una carpeta llamada Central Management Servers, como puede observarse en la siguiente figura. Disculpad aquellos que no utiliceis las versiones en inglés, entiendo que para un hispano hablante, quizá debiera usar esas versiones, pero por mi trabajo, me veo muy a menudo obligado a usarlo en inglés y prefiero no hacerme un lio con las traducciones. Mis disculpas al que le moleste.
Pulsando con el botón derecho sobre Central Management Servers nos aparecerá un  menú contextual con leyenda “Register Central Management Server”, este será el servidor que nos valga como nodo principal, por decirlo de una forma poco ortodoxa, pero bastante comprensible.  En el asistente nos permite especificar tanto una descripción como una forma de conectarse, en mi caso, lo haré con mi usuario Administrador y con seguridad integrada. Cabe destacar que para no almacenar contraseñas que además lo serían de usuarios con muchos privilegios, solamente está permitida la seguridad integrada, según se detalla en este artículo http://msdn.microsoft.com/en-us/library/bb934126(v=SQL.100).aspx Aquí simplemente hemos de conectarnos con los suficientes privilegios. (Son privilegios obviamente de administración de los servidores es decir, unos privilegios bastante elevados)
Tras comprobar que nos conectamos de forma adecuada, pulsaremos save, a partir de este momento hemos de añadir los servidores que serán administrados desde éste.  No es necesario añadirlo dentro de la subcarpeta Central Management Servers, es más podemos crear grupos de servidores que se comporten como tales. Por ejemplo, podemos crear un grupo Desarrollo, de forma que script aplicados a server de desarrollo se apliquen a tantos servidores de desarrollo como tengamos registrados.
Veamos un ejemplo de como hacerlo. Sobre “Local Server Groups” pulsamos botón derecho y “New SQL Server Group”, esto hace que creemos una carpeta común bajo la que ubicar servers. dentro de esa carpeta, botón derecho de nuevo y registraremos nuestros servers, como puede verse en la siguiente figura.
En el caso del ejemplo tenemos registrados dos servidores, en realidad son las instancias SQL 2008 R2 y SQL 2005 que tengo instaladas en mi equipo.
Si sobre el grupo Desarrollo, presionamos botón derecho new query, nos aparecerá una ventanita, en la que, podremos comprobar como la barra de estado, no es amarilla ni gris, sino de un color rosado, También nos dice cuantos servidores hay contectados. Cualquier query ejecutado ahí, se ejecutará en ambos servers. Ojo, con el tipo de queries que hacemos, puesto que pueden fallar. Suelo decir que cuando alguien ejecuta un SELECT * , Dios mata un gatito, es una broma que me gusta hacer y que en este caso cobra especial relevancia, en mi caso por ejemplo, si hago esto saldrá este mensaje.
.\SQK2K8R2(WIN-P3PS5OB2GSJ\Administrator): (15 row(s) affected)
.\SQL2K5(WIN-P3PS5OB2GSJ\Administrator): An error occurred while executing batch. Error message is: The result set could not be merged because the result schema did not match the schema from the first responding server.
.\SQL2K5(WIN-P3PS5OB2GSJ\Administrator): (8 row(s) affected)
Esto es básicamente porque lo que hace SQL Server Management Studio es ejecutar el mismo comando en ambos servers y unir el resultado como si de un UNION ALL se tratara. En mi caso, entre la versión SQL 2005 y la versión SQL 2008 R2, la tabla sys.sysdatabases tiene estructuras distintas, así pues.. no puede unir el resultado. Cambiaré ese * y así podré ver como si que funciona. La sentencia que ejecutaré y el resultado podeis verlo en la siguiente captura de pantalla. Notad como aparece una columna que yo no he solicitado ([Server Name]) que indica a que server pertenecen esos objetos.
Si os fijais ha aparecido esa columna que mencionabamos además de aparecer la barra de estado en color rosa.
Esta opción es una opción del propio SQL Server Management Studio,  tanto que mezcle los resultados ( lo que hablabamos antes y que tiene problemas con servidores con distintas versiones) tanto que añada el nombre del servidor o incluso el nombre de login. Si vamos al menú Tools (herramientas) a la opcion “Options” (Opciones), bajo Query Results, SQL Server veremos un apartado Multiserver Results  en el que controlar ese comportamiento. Obviamente podremos cambiarlo hasta que se adecúe lo mejor posible a nuestro propio entorno. Como puede verse en la siguiente figura.
Conclusion: SQL Server Management Studio, es una herramienta realmente potente, con un gran número de opciones y funcionalidades, algunas que permanecen ocultas para muchos, merece la pena bucear un poquito en su funcionamiento para realmente sacarle el máximo provecho.  En este caso, para la administración multi servidor.

Instalando la CTP3 de SQL Server 2011, CodeName Denali

Posted by Miguel Egea | Posted in Analisys Services, Noticias, Relacional | Posted on 23-08-2011

0

Aunque ya lo publicamos hace algun tiempo, la versión CTP3, del nuevo SQL Server está aquí. Desde el pasado Noviembre en que tuvimos acceso algunos pocoas a la CTP1, en PASS hasta ahora, muchas cosas han aparecido y están implementadas, ayer mismo linkabamos un avance de las novedades TSQL, muchas novedades en funciones de Ranking, algunas no incluidas en el artículo de Enrique.

Recordad que esto es una guía, y aunque omita pasos es muy muy sencilla.

Nota, yo lo he instalado en inglés, porque me siento más cómodo con las versiones en inglés.. creo que hay versión en castellano,

Lo bueno de las versiones CTP publicas es que todos podemos jugar con ellas, todos podemos cacharrear. Para que os hagais una idea de los pasos que hay que seguir voy a ir poniendo el paso a paso que yo he seguido. No será un tutorial al uso, omitiré seguramente cosas que me parezcan obvias. Espero no obstante, no omitir ninguna que el lector considere importante.

Comenzando con esto, lo primero que hemos de hacer es descargar la versión. Nos pedirá que nos registremos y podremos descargarlo. Podéis seguir este link para comenzar esa operación.

Una vez completado el proceso.. acabará teniendo una pantalla muy parecida a esta.

Hecha la descarga vamos a seguir con la instalación del producto, recordad elegir la versión adecuada, 32 o 64 bits a vuestro sistema operativo, y revisar los requisitos del sistema para asegurar que no perderéis el tiempo, es decir que finalmente conseguireis instalar.

Tras descargar, hemos de ejecutar el programita de setup, que realmente nos descomprimirá los fcheros en una carpeta, como podeis ver en las dos siguientes imágenes

y en la siguiente que podeis ver la carpeta donde está el fichero Setup.exe.. que habremos de ejecutar.

Al ejecutarlo, nos aparecerá la pantalla tipica desde SQL Server 2005, en donde está la parte de Planning, es decir donde decidimos y comprobamos los requisitos.

y tras eso, pulsaremos en Installation y haremos el setup que necesitemos ( en nuestro caso nueva instancia StandAlone)
>

Una vez elegida la instalación que vamos a realizar, el propio instalador comprueba que la instalación será exitosa, que no hay pre-requisitos pendientes para que funcione el instalador y nos ofrece este resumen de las cosas que ha comprobado. Este resumen, por defecto está escondido, pero se puede ver fácilmente.

Al pulsar siguiente aparecerá la pantalla de licencia, obviamente hemos de leer y aceptar los terminos de licencia, que es de evaluación de 180 dias, y continuar con la instalación.

El producto en ese momento se conecta a Internet para ver si hay actualizaciones de la CTP que aplicar, en mi caso detectó 2, y en sistemas no en producción, como es el caso, lo mejor es instalarlo todo. En producción es otra historia, hay que probar, al menos mínimamente que el impacto no es negativo.

Además de las comprobaciones del instalador y prerequisitos, el asistente también comprobará que no van a existir problemas conocidos con la instalación de los ficheros de soporte, así pues se comprueban estos 8 puntos. y tienen que pasar todos (aunque sea con warning) para que la instalación pueda completarse.

Tras las comprobaciones hay que ver que cosas queremos hacer. Instalar los servicios o quizá instalar PowerPivot para Sharepoint o quizá añadir funciones. En nuestro caso vamos a hacer una nueva instalación.

Ahora el Asistente nos permite seleccionar las herramientas que instalaremos, yo he instalado todo lo que tengo intención de probar, pero nada relacionado con Sharepoint puesto que no voy a probar, de momento esa parte.

Tras esto tenemos que elegir el nombre de instancia, en mi caso, además vereis que aparecen otras instancias ya instaladas, la edicion enterprise de SQLServer 2008 R2 y la edición developer de SQL SErver 2005. con las versiones y parches que tengo instalados. En mi caso puedo elegir default instance, porque no tengo ninguna instancia por defecto, aún así, he preferido poner como nombre de instancia SQLDenali, me gustan las instancias nombradas :) .

Permisos y cuentas: Esta parte, es muy importante en instalaciones no de test, como la mia. Yo suelo poner cuentas de dominio sin ningún privilegio, de esa forma el propio asistente da los permisos mínimos que necesita. Esto hace que luego esa cuenta no tenga acceso a muchos directorios, pero eso, que puede ser percibido como un problema, es sin embargo una norma de seguridad básica.
Otra pestaña, de la que no ponemos mensaje, pero que es necesario saber que hace es la de Collation, esto indicará el modo por defecto del servidor, es decir el modo por defecto de las bases de datos, y el modo por defecto de cada columna de texto. Es importante porque cada Collation lleva implicito una ordenación, si distingue o no entre mayúsculas y minúsculas… en fin que no es algo de poca importancia.

Tras dejar cerrado el apartado seguridad y colation, llegamos al apartado de Analysis Services Configuration (esto supongo que solo sale si has instalado Analysis Servcies). Esta nueva versión lleva incorporado un nuevo modo, además del tradicional, Ambos no pueden funcionar a la vez en la misma instancia. Digamos que TAbular Mode es una especie de PowerPivot de Servidor, pero no tiene, aún al menos, toda la potencia que esperamos de analisis services, tiempo tendremos de ir hablando sobre él.
De momento en esta instalación instalaremos el modo tradicional.

DEspues de pulsar siguiente.. el instalador ya tiene los datos que necesita…. ahora paciencia. A esperar a que termine la instalación y a disfrutar del siguiente cartel, cuando salga.

Espero que os resulte de utilidad.

Novedades en SQL Server 2011 por Enrique Catalá

Posted by Miguel Egea | Posted in Noticias, Relacional | Posted on 21-08-2011

0

Repasando los contenidos de mis compañeros del mundo relacional he encontrado este interesantísimo post, especialmente recomendado para aquellos que os gusta ir un pasito por delante, en el artículo Enrique cuenta las novedades T-SQL que trae la nueva versión de SQL Server

Si quereis más información. seguid este Enlace

Backups del log, cuando sean necesarios

Posted by Miguel Egea | Posted in Relacional | Posted on 19-08-2011

0

Este es un mini-artículo, tip, que escribí en 2003 y que he creido interesante recuperar. Es una de esas cosas que periodicamente alguien te vuelve a preguntar, y aunque pueda parecer extraño, parece uno de esos temas que no pasan de moda.

Introducción

El crecimiento de log de transacciones es sin duda alguna la pregunta número uno en los grupos y foros de noticias, por eso entiendo, que cualquier cosa que aclare un poquito como funciona será beneficioso. Mi amigo Ivan del rincón del programador , me sugería hace un ratillo que estaría bien algo así como un backup del log ‘bajo demanda’.

La verdad es que no hay un evento o trigger que nos vaya a servir para hacerlo bajo demanda, pero siempre podemos crear un job que llame a este procedimiento almacenado y que por tanto nos mantenga nuestro fichero de log bajo control. Al ser el log una estructura circular, si le hacemos backup cuando esté muy lleno, no va a crecer, sino a rehusar el espacio que marcamos como libre por el mero hecho de hacer la copia. De hecho veréis que si ejecutáis dos veces el procedimiento almacenado, realmente la segunda no hará ninguna copia. Claro, estará prácticamente vacío.

Ya sabéis que prefiero el código a las explicaciones así que os pongo el procedimiento almacenado en cuestión. La verdad es que está bastante comentado.

Suerte y gracias por seguirnos.

El código

if not object_id('backupwhennecesary') is null
    drop proc backupWhenNecesary
go
create proc backupWhenNecesary (@file sysname)
as
    begin
        -- primero que no se produzcan salidas no deseadas--
        set nocount on
        -- Necesitamos la tabla y la ruta en la que hacer el backup --
        -- podría ser a cinta directamente, pero en mi portatil no --
        -- tengo systema de cintas, así que,no puedo probarlo --
        declare @tabla sysname
        Declare @fileabs sysname
        -- Creamos una tabla temporal para guardar el resultado de --
        -- DBCC --
        create table #temp (nombre sysname,tam float,pct float,status int)
           insert into #temp exec('DBCC sqlperf(logspace)')
            -- Usaremos un cursor, ¡sí, yo también uso cursores!, poco --
          -- pero alguna vez :-D --
        declare cr Cursor for 
            select nombre from #temp where pct>75 
                                        and DATABASEPROPERTYEX(nombre, N'RECOVERY')<>'SIMPLE' 
        -- 75 porciento de uso, si queréis más o menos,...
        -- el modelo de recuperación si es simple no permite
        -- hacer backup de log, y nosotros no queremos que nuestro
        -- procedimiento almacenado falle :-D
        open cr
        fetch next from cr into @tabla
        while @@fetch_status=0
            begin
                -- construyo de forma dinámica el nombre del fichero en
                -- donde guardaremos la copia de seguridad
 
 
 
-- modificamos este trozo de código el día 13 de agosto de 2003 
 
-- El código nos lo propone el maestro Fernando Guerrero y con esta modificación guardamos ficheros
 
-- de log independientes, en lugar de todo en un solo fichero. 
             set @fileabs=@file
                        + '_'
                        + @tabla 
                        + '_'
                        + select 
                        replace(
                        replace(
                        replace(
                        replace(
                        convert(varchar(25), getdate(), 121)
                        , '-', '')
                        , ' ', '_')
                        , ':', '')
                        , '.', '')
                +'.trn'
                    -- fin modificación
 
                -- ejecutamos la copia
                exec sp_executesql N'backup log @p1 to disk= @p2 ',N'@p1 sysname, @p2 sysname',@tabla,@fileabs
                    -- a la siguiente bd.
                fetch next from cr into @tabla
            end
        -- cerramos
        close cr
        -- liberamos
        deallocate cr
        -- y borramos nuestras tablas...
        drop table #temp 
end
go

Tip: Roles y permisos en SQL SErver

Posted by admin | Posted in Relacional | Posted on 15-08-2011

0

Hoy, un compañero de los grupos de noticias de SQL Server preguntaba sobre como gestionar los permisos de roles y usuarios en el grupo de noticias sobre SQL server en castellano. Me gustó la pregunta así que me permito copiaros mi respuesta (aunque aún no se si es la buena) este es el post

Y esta mis respuesta

Los usuarios para tener acceso han existir en las bases de datos, o bien, darle permisos a public, yo te sugiero que hagas algo como lo que hace el siguiente script. Obviamente, estamos dando muchos permisos.. así que quizá, si la seguridad es un factor importante podrías pensarte bien si es la situación adecuada. (ojo con el script que al final borro las bases de datos.. a ver si vamos a tener un disgusto :-) )

create database tesoreria;
go
create database contabilidad;
go
create login a with password=’Contra1Se@ia’;
create login b with password=’Otr0P@sss’;
go
use tesoreria;
go
create user a for login a;
create user b for login b;
create role leeryejecutar;
exec sp_addrolemember ‘leeryejecutar’,'a’;
exec sp_addrolemember ‘leeryejecutar’,'b’;
go
declare @sql nvarchar(max)
set @sql=”;
select @sql=@sql+’GRANT DELETE, INSERT, SELECT, UPDATE ON ‘ +QUOTENAME(table_schema)+’.'+ quotename(TABLE_NAME) +’ TO leeryejecutar;’ from INFORMATION_SCHEMA.TABLES ;/* tablas y vistas */
exec sp_executesql @sql,N”
set @sql=”;
select @sql=@sql+’GRANT EXEC ON ‘ + QUOTENAME(ROUTINE_SCHEMA)+’.'+QUOTENAME(ROUTINE_NAME) +’ TO leeryejecutar;’ from INFORMATION_SCHEMA.ROUTINES ;/* tablas y vistas */
exec sp_executesql @sql,N”
go
use contabilidad;
create table a(id int);
go
create procedure PROC_a @id int as begin select * from a end ;
go
create user a for login a;
create user b for login b;
create role leeryejecutar;
exec sp_addrolemember ‘leeryejecutar’,'a’;
exec sp_addrolemember ‘leeryejecutar’,'b’;
go
declare @sql nvarchar(max)
set @sql=”;
select @sql=@sql+’GRANT DELETE, INSERT, SELECT, UPDATE ON ‘ +QUOTENAME(table_schema)+’.'+ quotename(TABLE_NAME) +’ TO leeryejecutar;’ from INFORMATION_SCHEMA.TABLES ;/* tablas y vistas */
exec sp_executesql @sql,N”
set @sql=”;
select @sql=@sql+’GRANT EXEC ON ‘ + QUOTENAME(ROUTINE_SCHEMA)+’.'+QUOTENAME(ROUTINE_NAME) +’ TO leeryejecutar;’ from INFORMATION_SCHEMA.ROUTINES ;/* tablas y vistas */
exec sp_executesql @sql,N”
go

use master;

drop database contabilidad;
drop database tesoreria;
drop login a;
drop login b;