mercredi 12 mars 2014

SSIS : Paramétrer un Lookup en mode Full Cache

Utiliser une requête dynamique (expression SSIS) dans un Lookup en mode Full Cache, cela peut s’avérer indispensable si l’on veut réduire dynamiquement le volume de données à monter en cache. Notamment, dans le cas de traitements itératifs, et que l’on ne veut pas monter en cache tout le contenu de la table/requête à chaque itération, mais juste ce qu’il faut.

En effet, même si l'interface du composant Lookup n'expose pas directement la possibilité d'utiliser des variables comme dans les sources OLEDB ou une expression dans la propriété "SqlCommand" comme dans les tâches d’exécution SQL. Le composant Lookup dispose bien d'une propriété "SqlCommand" paramétrable, sauf que celle-ci est exposée au niveau du flux de données (DFT), comme le montre la capture d'écran suivante :


Pour le mode opératoire rien de plus simple :

  • Configurer le Lookup avec une requête sans variable afin de l'initialiser et faire le mapping. 
  • Sélectionner au niveau du DFT la propriété "[Nom du Lookup].[SqlCommand]" du Lookup à paramétrer et spécifier la requête à utiliser avec la bonne variable dans la partie "Expression".




mardi 4 mars 2014

[SQL] : Suppression de tous les utilisateurs d'une base SQL Server

Dans cet article, je vais parler d'un sujet que je viens de traiter et qui consiste à faire le ménage au niveau des bases de données récupérées d'un serveur et restaurées sur un autre. Et cela en supprimant tous les utilisateurs de ces bases de données, afin d'y appliquer une sécurité un peu plus restrictive.

Avant de pouvoir supprimer des utilisateurs ou des rôles SQL, il faut allouer tous les schémas au rôle "dbo". En effet, on ne peut pas supprimer un utilisateur ou un rôle qui est "owner" d'un schéma.

Pour cela, un curseur sur tous les schémas :

DECLARE @SchemaName SYSNAME,@SQL NVARCHAR(1000)
DECLARE SchemaNames CURSOR FOR
      SELECT s.name FROM sys.schemas s
      WHERE s.principal_id NOT IN (SELECT dp.principal_id 
                                   FROM sys.database_principals dp 
                                   WHERE dp.is_fixed_role=1 OR name IN                                         ('dbo','guest','INFORMATION_SCHEMA','sys','public'))
OPEN SchemaNames
FETCH NEXT FROM SchemaNames INTO @SchemaName
WHILE @@FETCH_STATUS = 0
BEGIN
      SET @SQL = 'ALTER AUTHORIZATION ON SCHEMA::[' + @SchemaName + '] TO dbo'
      EXEC sp_executesql @SQL
      FETCH NEXT FROM SchemaNames INTO @SchemaName
END
CLOSE SchemaNames

DEALLOCATE SchemaNames;

La deuxième étape consiste à supprimer les utilisateurs ainsi que les rôles de base de données, et là aussi il y a une contrainte, c'est qu'on ne peut pas supprimer un utilisateur référencé dans un rôle.
Pour cela, la suppression sera faite en deux étapes:
  • Suppression des utilisateurs référencés dans chaque rôle via un "sp_droprolemember" avant de supprimer le rôle même.
  • Puis suppression des utilisateurs.

Voici le script complet :

DECLARE @LoginRoleName SYSNAME,@SQL NVARCHAR(1000),@Type VARCHAR(1)
DECLARE DBROLELOGINS CURSOR FOR

SELECT NAME,[type] FROM sys.database_principals
WHERE name NOT IN ('dbo','guest','INFORMATION_SCHEMA','sys','public')
AND is_fixed_role = 0

OPEN DBROLELOGINS
FETCH NEXT FROM DBROLELOGINS INTO @LoginRoleName, @Type
WHILE @@FETCH_STATUS = 0
BEGIN
IF @Type = 'R'
BEGIN
--DECLARE @RoleName sysname
--set @RoleName = @LoginRoleName
BEGIN
      DECLARE @RoleMemberName sysname
      DECLARE Member_Cursor CURSOR FOR
      select [name]
      from sys.database_principals
      where principal_id in (
            select member_principal_id
            from sys.database_role_members
            where role_principal_id in (
                  select principal_id
                  FROM sys.database_principals where [name] = @LoginRoleName  AND type = 'R' ))

      OPEN Member_Cursor;

      FETCH NEXT FROM Member_Cursor
      into @RoleMemberName

      WHILE @@FETCH_STATUS = 0
      BEGIN

            exec sp_droprolemember @rolename=@LoginRoleName, @membername= @RoleMemberName
            PRINT @LoginRoleName
            FETCH NEXT FROM Member_Cursor
            into @RoleMemberName
      END;

      CLOSE Member_Cursor;
      DEALLOCATE Member_Cursor;
END
SET @SQL = 'DROP ROLE [' + @LoginRoleName + ']'
EXEC sp_executesql @SQL
PRINT @SQL
END
IF @Type <> 'R'
BEGIN
SET @SQL = 'DROP USER [' + @LoginRoleName + ']'
PRINT @SQL
EXEC sp_executesql @SQL
END
FETCH NEXT FROM DBROLELOGINS INTO @LoginRoleName,@Type
END
CLOSE DBROLELOGINS
DEALLOCATE DBROLELOGINS;

[SQL] : Suppression de plusieurs tables sans utilisation de curseur

Un petit post rapide pour montrer comment supprimer plusieurs tables sans passer par un curseur.

Dans mon cas, le but était de supprimer toutes les tables du schéma "staging" afin d'en recréer, que celles qui sont vraiment utilisées.

Pour cela, une façon rapide consiste à utiliser le script suivant :

USE MyDB
GO
DECLARE @cmd VARCHAR(MAX)=''
SELECT
@cmd = @cmd + 'DROP TABLE ' + TABLE_NAME + ';
'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'stg'
PRINT (@cmd)

EXEC (@cmd)


Ce script peut être adapté pour d'autres cas d'usages.