Webcast : Integrando Reporting Service 2008 a Sharepoint

by 18. julio 2009 22:43

El día viernes 17 de julio di un webcast en el cual mostré las ventajas de la integración de reporting service con sharepoint, además se ve en el mismo la forma de configuración  , los cuidados que hay que tener y por ultimo un sitio funcionando.

Aquí les dejo el link para que puedan ver el video ondemand

Tags:

Comunidad | SQL 2008

Comprimiendo datos y backups en SQL Server 2008

by 18. julio 2009 20:54

El día jueves 16 de Julio he dado un webcast en el cual mostré las distintas opciones de compresión tanto a nivel datos como backups que hay en SQL Server 2008, una funcionalidad totalmente nueva.

Aquí les dejo el material del mismo para quienes lo deseen descargar

Tags:

Comunidad | SQL 2008

Error inesperado en Sharepoint consumiendo reportes de Reporting Service

by 9. julio 2009 23:46

Si tienen integrado a Sherepoint (ya sea el portal o bien el services) son Reporting services y ejecutan un reporte que dura mas de dos minutos les aparecerá del lado de Sharepoint el siguiente error: Error inesperado o bien “An unexpected error has occurred” en ingles.

Por defecto existe un timeout a nivel ASP que es de 2 minutos, para cambiar este valor habrá que hacer los siguientes pasos desde el servidor de Sharepoint

  1. Abrir el archivo web.config de la aplicación sharepoint (por ejemplo \inetpub\wwwroot\wss\VirtualDirectories\80)
  2. Buscar dentro del archivo httpRuntime
  3. Agregar executionTimeout con un valor en segundos deseado, por ejemplo 1800

<httpRuntime maxRequestLength="51200" executionTimeout = "1800" />

Esto nos permitirá extender el timeout del sharepoint haciendo que si tenemos reportes con una duración mayor a dos minutos los podamos ejecutar sin errores. Les recomiendo poner 1800 segundos ya que también ese valor es el predeterminados a nivel Reporting Service para un timeout de Reporte.

Aquí les dejo el link original de donde he sacado la solución y me ha funcionado perfecto.

Tags:

How To

Generando Script de estructuras y datos con el Management Studio

by 9. julio 2009 21:22

Una de las operaciones que muchas veces necesitamos hacer es la de poder generar script de las estructuras de nuestros objetos o bien de toda una base de datos.

Esta opción esta disponible desde viejas versiones del producto donde con el Enterprise Manager o bien el Management Studio de 2005 se podía hacer lo mas bien.

Pero hasta SQL 2008 lo único que nos dejaba generar script eran justamente estructuras y no datos de ellas (registros).

Imaginemos que tenemos una tabla de configuración que necesitamos además de hacer el script de las estructuras que también incluya los registros, para lo cual se debería transformar en sentencias INSERT de nuestro script .SQL.

Para poder hacer este tipo de tareas por lo general debíamos recurrir a herramientas de terceras partes, ahora y a partir de SQL Server 2008 usando el Management Studio (el de Express también lo soporta y es gratuito) podemos a nuestros script darle la posibilidad de generar datos.

Aquí les muestro como lo hacemos

Primero debemos entrar al SSMS (SQL Server Management Studio) para conectarnos al servidor.

Luego sobre la solapa base de datos, pulsaremos el botón alterno del mouse para seleccionar Task y luego Generate Script el cual nos aparecerá el siguiente Wizard.

image

Lo que aquí debemos seleccionar es la base de datos a la cual necesitamos armar los script, por ejemplo MUG1 y luego pulsar sobre el botón siguiente, al hacer esto nos aparecerá una segunda ventana con distintas opciones, por ejemplo si queremos generar los script de índices, los logins, etc.

En el SSMS de 2008 tenemos un nuevo chiche y es que una de esas opciones en la sección de tablas es de generar la data, debemos poner en true (viene en false por defecto)

image

Al seleccionar esa opción ya nuestro script resultante no solo incluirá las estructuras sino que también los datos con sentencias INSERT.

La siguiente ventana nos permite seleccionar que tipos de objetos queremos hacer el script, para este ejemplo seleccionaremos Tables

image

Al seguir al nuevo paso tendremos el listado de tablas las cuales podemos seleccionar o una o mas de una

image

Por ultimo nos preguntara el wizard donde queremos enviar el resultado, aquí yo le pondré en una nueva ventana para que podamos observarlo

image

Bien, luego de hacer esto y dejar que termine el proceso, tendremos en nuestra nueva ventana el script resultante.

Aquí copio mi resultado donde se podrá observar que no solo armo las sentencias DDL para la tabla sino que también las DML para insertar el registro que tiene la tabla.

USE [MUG1]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO

CREATE TABLE [ventas].[Clientes](
    [Codigo] [varchar](15) NOT NULL,
    [Nombre] [varchar](100) NULL,
    [Direccion] [varchar](100) NULL,
    [fecha] [date] NULL,
    [id] [int] IDENTITY(100,10) NOT NULL,
    [fecha_nac] [date] NULL,
 CONSTRAINT [PK_Clientes_1] PRIMARY KEY CLUSTERED 
(
    [Codigo] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

SET ANSI_PADDING OFF
GO
SET IDENTITY_INSERT [ventas].[Clientes] ON
INSERT [ventas].[Clientes] 
([Codigo], [Nombre],[Direccion], 
[fecha], [id], [fecha_nac]) 
VALUES (N'1', N'mug', N'riv...', NULL,
100, CAST(0x16310B00 AS Date))

Tags:

How To

Sql Dinámico y seguridad en SQL2005

by 9. julio 2009 17:47

 

SQL-Dinámico y seguridad dentro de SQLServer 2005

El SQL-dinámico es una técnica la cual nos permite ejecutar sentencias TSQL de forma dinámica,  para poder hacer uso de esta técnica es necesario utilizar o bien el store procedure sp_executesql o sino EXEC(@str).

Este articulo no tiene como objetivo entrar en detalle del SQL-dinámico ya que hay otros escritos al respecto como por ejemplo el siguiente link el cual recomiendo leer

 

Aquí nos concentraremos en la seguridad y los cambios que hay en SQL2005 al respecto.

Una de las mayores contras que tiene el uso de SQL-Dinámico es que si lo ponemos dentro de un Store Procedure el usuario que ejecute tal Store no solo deberá tener permisos de execute sino que también deberá tener permisos sobre los objetos que haga referencia el SQL-Dinámico.

Para poder ser más específicos veamos un ejemplo al respecto

USE

MASTER

GO

CREATE DATABASE TEST1

GO

USE TEST1

GO

-- CREAMOS UN NUEVO LOGIN

CREATE

LOGIN FEDERICO WITH PASSWORD ='PASSW@RD'

GO

USE TEST1

GO

-- CREAMOS EL USUARIO EN LA BASE DE DATOS

CREATE USER FEDERICO

GO

-- CREAMOS UNA TABLA

CREATE

TABLE DBO.EMPLEADOS (ID INT IDENTITY, NAME VARCHAR(50))

GO

-- CREAMOS UN STORE QUE CONSUME LA TABLA EMPLEADOS

CREATE

PROC DBO.USP_EMPLEADOS_GET_ALL AS
SELECT * FROM DBO.EMPLEADOS

GO

-- CREAMOS OTRO STORE QUE CONSUME LA TABLA PERO CON SQLDINAMICO

CREATE

PROC DBO.USP_EMPLEADOS_GET_ALL2 AS

DECLARE @N NVARCHAR(50)

SET @N = N'SELECT * FROM DBO.EMPLEADOS'
EXECUTE SP_EXECUTESQL @N

GO

-- FEDERICO SOLO TIENE PERMISOS A LOS STORES

GRANT

EXECUTE ON DBO.USP_EMPLEADOS_GET_ALL TO FEDERICO
GRANT EXECUTE ON DBO.USP_EMPLEADOS_GET_ALL2 TO FEDERICO

GO

-- ENTRAMOS COMO FEDERICO

EXECUTE

AS LOGIN = 'FEDERICO'

SELECT

SUSER_SNAME()

SELECT

* FROM DBO.EMPLEADOS -- FALLA PORQUE NO TENEMOS PERMISO

EXEC

DBO.USP_EMPLEADOS_GET_ALL -- FUNCIONA

EXEC

DBO.USP_EMPLEADOS_GET_ALL2 -- FALLA POR EL SQL-DINAMICO

REVERT

-- REVERTIMOS EL LOGIN

Como se ha podido observar en el ejemplo el segundo Store ha fallado cuando el usuario Federico lo invoco ya que no tenia permisos sobre los objetos internos del mismo, en este caso la tabla "Empleados".

Esto atenta contra el buen uso de un Store procedure ya que una de sus virtudes es aislar a los usuarios del acceso directo a los objetos, con lo cual si deseamos en este caso usar SQL-Dinámico deberíamos darle permisos de Select a la tabla correspondiente.

Esto funciona así en 2000 y no hay solución al respecto, por lo cual yo no recomiendo mucho el uso de SQL-Dinámico y de usarlo tener en claro lo que está sucediendo.

¿Que cambios hay en 2005?

SqlServer 2005 permite dentro de un objeto como el Store Procedure indicarle el contexto de ejecución, esto es totalmente nuevo y se indica con la sentencia WITH EXECUTE AS (Caller, Owner o Username)

  • Caller es utilizado por defecto y representa a quien llama (como vimos en el ejemplo 1)
  • Owner indica que se impersonificara como el usuario propietario del objeto, en este caso como entre con la cuenta de SA entonces estamos impersonificando con ella.
  • User_name nos permite indicar con que login deseamos que se impersonifique

 

El siguiente ejemplo modifica el  Store con SQL Dinámico pero utilizando Execute AS

-- CAMBIOS EL STORE DEL SQL DINAMO PARA QUE SE EJECUTE EN

-- OTRO CONTEXTO DE SEGURIDAD

ALTER PROC DBO.USP_EMPLEADOS_GET_ALL2

WITH EXECUTE AS OWNER

AS

DECLARE @N NVARCHAR(50)

SET @N = N'SELECT * FROM DBO.EMPLEADOS'
EXECUTE SP_EXECUTESQL @N

GO

-- VOLVEMOS A PROBAR

EXECUTE

AS LOGIN = 'FEDERICO'

SELECT

SUSER_SNAME()

SELECT

* FROM DBO.EMPLEADOS -- FALLA PORQUE NO TENEMOS PERMISO

EXEC

DBO.USP_EMPLEADOS_GET_ALL

EXEC

DBO.USP_EMPLEADOS_GET_ALL2

REVERT

Aquí se ve claramente que ahora Federico no necesito permisos sobre la tabla "Empleados" para poder hacer uso del SQL-Dinámico.

Con esto lo que logramos es seguir manteniendo una de las enormes virtudes que tienen los Stores Procedures que es el aislamiento con respecto a los objetos base.

No confundir el Execute AS del Store con el luego utilizado en el query para dentro del management Studio impersonificarnos como Federico sin la necesidad entrar a otra ventana.

Estos ejemplos deben ser probados desde SQL2005, si desea probar el primer ejemplo desde SQL2000 deberá sacar la sentencia Execute AS y probar la seguridad entrando con el correspondiente login y password.

Bueno espero les sea de utilidad y espero sus comentarios.

Nos vemos!

Tags:

How To

Como generar el numero de nuestros comprobantes sin morir en el intento

by 9. julio 2009 17:44

En la mayoría de nuestras aplicaciones tenemos la necesidad de poder generar el numero de nuestros comprobantes (Ordenes de compra, pedidos de ventas, etc.)

Existen diferentes técnicas para poder realizar esta operación. En los ejemplos de este post mostrare las dos formas mas tradicionales de hacerlo y cuales son sus pros y contras de cada una.

Para estos ejemplos crearemos una base de datos nueva con la siguiente sentencia

CREATE

DATABASE EJEMPLO_NUMERACION

Usando auto numéricos

Dentro de SQLserver podemos definir en un tipo de dato entero la posibilidad de que sea autoincrementar, esto hará que de forma automática el motor de base de datos calcule el valor que debe ir en ese campo. Usando esta posibilidad podríamos definir que en nuestros comprobantes el campo de numero sea auto numérico.

El siguiente ejemplo ilustra como hacer esta operación

USE

EJEMPLO_NUMERACION

GO

CREATE

TABLE OC (ID INT IDENTITY, FECHA DATETIME NOT NULL,

CLIENTE VARCHAR(50) NOT NULL)

GO

Como se podrá observar el campo ID es de tipo int y a su vez tiene la propiedad de ser autoincremental, el resto de los campos corresponden a datos necesarios de la Orden de compra de este ejemplo.

Si queremos insertar un nuevo registro (o sea una nueva orden de compra) simplemente hacemos lo siguiente

INSERT

INTO OC (FECHA,CLIENTE)

VALUES

(GETDATE(),'IBM')

go

Si luego de esto hacemos un select a la tabla OC y vemos los registros podremos observar que se ha generado de forma automática el ID 1, si hacemos otro insert valido veremos que se generara el 2 y así sucesivamente.

Ahora bien, que sucede si por ejemplo hacemos un insert y no se pudo realizar la transacción, por ejemplo queremos insertar una OC donde el campo Cliente sea nulo lo cual no esta permitido por  la integridad de la base de datos.

INSERT

INTO OC (FECHA,CLIENTE)

VALUES

(GETDATE(),NULL)

go

Al hacer esta instrucción recibiremos el siguiente error:

Msg 515, Level 16, State 2, Line 2

Cannot insert the value NULL into column 'CLIENTE', table 'EJEMPLO_NUMERACION.dbo.OC'; column does not allow nulls. INSERT fails.

 

Bien, el registro si hacemos un select a la tabla no se ha generado y eso es correcto ya que ha existido un problema.

Ahora bien, hasta el momento solo tenemos generada la OC con ID = 1 y la 2 ha fallado. Pues arreglamos el tema del null en el insert para que se genere la OC = 2 ya que es la que continua luego de la 1.

INSERT

INTO OC (FECHA,CLIENTE)

VALUES

(GETDATE(),'MICROSOFT')

go

El registro se genero ahora "correctamente", pero si hacemos un select a la tabla nos encontraremos que ahora tenemos el ID = 1 y el ID = 3, con lo cual estamos teniendo huecos en nuestra numeración.

Como se podrá observar es un grave problema tener estos huecos en los números de los comprobantes (imagine que fueran facturas por ejemplo), pues esto se debe a como funciona el auto númerico de SQLServer, es simple de usar e implementar pero hay que saber lo de las transacciones, ante una falla el numero lo reservo igual y considero que se genero con lo cual lo salta [:(]

Usando tabla numeradora

Otra alternativa a la que vimos es la de generar una tabla donde tendremos los números de los comprobantes y usarla para numerar uno nuevo, si la transacción fallo simplemente hay que tener el recaudo de no cambiar el valor en la tabla numeradora.

Entonces, lo primero que generamos es esta tabla numeradora

CREATE

TABLE NUMERADOR (TIPO_COMPROBANTE VARCHAR(100),

ULTIMO_NUMERO INT)

GO

INSERT

INTO NUMERADOR VALUES ('OC',1)

INSERT

INTO NUMERADOR VALUES ('FACTURAS',10)

GO

La tabla numeradora podrá ser utilizada por distintos comprobantes, de ahí es que tiene un campo denominado tipo_comprobante y otro ultimo_numero.

Como también se puede observar se le han insertado 2 registros, uno para los comprobantes de Ordenes de Compra y el otro para facturas.

Ahora bien, lo que debemos hacer como siguiente paso es utilizar esta tabla numeradora para obtener el ultimo_numero sumarle 1 y asignarlo a la OC que estamos generando. Aquí entran a jugar una serie mas de detalles a conocer, si hacemos un Select (sin cambiar el nivel de bloqueo) y otro usuario en otro sitio hace lo mismo podrán obtener el mismo ultimo_numero lo cual al sumarle 1 los dos intentaran hacer la misma OC.

Para evitar este tipo de situaciones, ya que no solo necesito numerar sino también asegurar que no exista la posibilidad de obtener números duplicados (la misma OC por ejemplo) es que vamos a hacer uso de algunos trucos de bloqueos y variables.

DROP

TABLE OC

GO

CREATE

TABLE OC (NUMERO INT, FECHA DATETIME,CLIENTE VARCHAR(50) NOT NULL)

GO
declare @proximo_numero int
begin try

begin

tran

update numerador set @proximo_numero = ultimo_numero = ultimo_numero + 1

where tipo_comprobante = 'OC'

INSERT INTO OC VALUES (@proximo_numero,getdate(),'SQLTOTAL')

commit tran
end try

begin

catch

rollback tran -- primero hacemos un rollback

print @@error -- mostramos el error generado

end

catch

GO

La sentencia UPDATE no solo modifica la tabla sino que además actualiza la variable que luego utilizamos para generar el comprobante. De esta manera logramos que si hay 2 procesos haciendo esto por el uso de los bloqueos internos de SQL al hacer uso de la instrucción UPDATE, el segundo proceso no podrá hacer update hasta que el primero no haya terminado la transacción (ya sea por commit o rollback tran)

Si hacemos un select sobre OC vamos a observar que se ha generado el id numero 2, ahora bien si intentamos hacer un nuevo insert pero que falla y luego volvemos a insertar uno que no falla no tendremos los huecos en la numeración como nos ha sucedido con los identity.

Para probar que no se van a generar 2 números iguales en tiempos iguales hay que hacer la siguiente prueba con el Script.

1) Habrá dos ventanas de management studio o Query Analizer si usa 2000

2) En ambas copie por ejemplo este código

declare @proximo_numero int begin try

begin

tran

update numerador set @proximo_numero = ultimo_numero = ultimo_numero + 1

where tipo_comprobante = 'OC'

INSERT INTO OC VALUES (@proximo_numero,getdate(),'SQLTOTAL')
end try

begin

catch

rollback tran -- primero hacemos un rollback

print @@error -- mostramos el error generado

end

catch

3) Ejecute desde la primer ventana el script, luego hágalo desde la segunda. Como podrá observar en la segunda ventana se queda esperando y no procesa , esto se debe que hay bloqueos sobre la tabla numeradora y que el segundo update no ha podido ser realizado.

4) En la primer ventana escriba commit tran y ejecute solo eso

Al hacer esto podrá observar que la segunda ventana ha terminado.

5) Haga un select sobre OC y vea los resultados [:)]

 

Bueno con esto termino, espero que les haya sido de utilidad y espero sus comentarios

 

 

Tags:

How To

Como evitar que se acceda a nuestro SQL vía Excel

by 9. julio 2009 17:36

En nuestras empresas o en clientes hay muchas veces que tenemos la necesidad de restringir el acceso a nuestro SQL desde ciertas aplicaciones como podría ser el paquete Office. A partir de SQL Server 2005 y con la incorporación de los triggers DDL podemos hacer esto de forma bastante simple.

Aquí les dejo un ejemplo de trigger DDL a nivel servidor de base de datos que no permitirá login desde aplicaciones Office.

CREATE TRIGGER [connection_limit_trigger]
ON ALL SERVER
FOR LOGON
AS

set nocount on

-- con este trigger controlamos quienes no pueden hacer login a SQL

BEGIN
IF app_name() like '%Office%'
    ROLLBACK;
END;
GO

SET ANSI_NULLS OFF
GO

SET QUOTED_IDENTIFIER OFF
GO

ENABLE TRIGGER [connection_limit_trigger] ON ALL SERVER
GO

Tags:

Error al querer eliminar un job de SQL Server 2005

by 9. julio 2009 17:34

Al intentar eliminar un Job del SQL Server 2005 puede aparecer el siguiente mensaje de error

The DELETE statement conflicted with the REFERENCE constraint “FK_subplan_job_id”. The conflict occurred in database “msdb”, table “dbo.sysmaintplan_subplans”, column ‘job_id’.
The statement has been terminated. (Microsoft SQL Server, Error: 547)

nos indica que no se puede eliminar un job por problemas con los planes de mantenimiento.

Para poder resolver este problema y poder eliminar el Job les dejo el siguiente Script

declare @job_name varchar(500)

set @job_name = N'tujob' ;

 

USE [msdb]

delete sysmaintplan_log

FROM sysmaintplan_subplans AS subplan

INNER JOIN

sysjobs_view AS jobs ON subplan.job_id = jobs.job_id INNER JOIN

sysmaintplan_log ON subplan.subplan_id = sysmaintplan_log.subplan_id

WHERE (jobs.name = @job_name)

 

delete sysmaintplan_subplans

FROM sysmaintplan_subplans AS subplan INNER JOIN

sysjobs_view AS jobs ON subplan.job_id = jobs.job_id

WHERE (jobs.name = @job_name)

 

delete

from msdb.dbo.sysjobs_view where name = @job_name

Tags:

How To

Material del Webcast sobre Resource Governor de SQL Server 2008

by 4. julio 2009 02:50

Hola, aquí les dejo el material que use en el webcast de Resource Governor.

Recuerden que pueden bajar el video desde el siguiente link

 

Material Resource Governor DemoRG

Tags:

SQL 2008

Guía de entrenamiento en SQL Server 2008 para desarrolladores

by 1. julio 2009 23:38

Aquí les dejo el siguiente link de la guía que publico Microsoft para desarrolladores sobre SQL Server 2008.

Hay presentaciones, demos y mucho mas

Tags:

Material

Webcast de Resource Governor SQL 2008

by 1. julio 2009 06:13

En Julio inicio una serie de Webcast (Eventos online y gratuitos) para Microsoft.

En el primero de esta serie (unos 5 serán) estaré mostrando Resource Governor, una nueva funcionalidad que viene con SQL Server 2008 y nos permite controlar el uso de los recursos (por ejemplo podríamos indicar a una aplicación dentro de SQL cuanto le damos de CPU o memoria)

En esta demo veremos no solo los conceptos teóricos sino que también nos concentraremos en la configuración y el funcionamiento, veremos una demo en vivo de como funciona este nuevo recurso en un ambiente real.

Este evento esta orientado a DBA

Tags:

New Sql 2008

Maximiliano Damian Accotto