Quelle est la meilleure méthode pour vérifier si un fichier existe à partir d’une procédure stockée SQL Server 2005 ?

StackOverflow https://stackoverflow.com/questions/16634

  •  08-06-2019
  •  | 
  •  

Question

Nous avons utilisé la procédure stockée xp_fileexist "non documentée" pendant des années dans SQL Server 2000 et n'avons eu aucun problème avec elle.En 2005, il semble qu'ils aient légèrement modifié le comportement pour toujours renvoyer un 0 si le compte utilisateur en cours d'exécution n'est pas un administrateur système.Il semble également renvoyer un zéro si le service SQL Server s'exécute sous le compte LocalSystem et que vous essayez de vérifier un fichier sur le réseau.

J'aimerais m'éloigner de xp_fileexist.Quelqu'un a-t-il un meilleur moyen de vérifier l'existence d'un fichier sur un emplacement réseau depuis une procédure stockée ?

Était-ce utile?

La solution

Peut-être qu'une procédure stockée CLR est ce que vous recherchez.Ceux-ci sont généralement utilisés lorsque vous devez interagir avec le système d’une manière ou d’une autre.

Autres conseils

Vous devrez marquer le CLR comme EXTERNAL_ACCESS afin d'avoir accès à l'espace de noms System.IO, mais au fur et à mesure que les choses évoluent, ce n'est pas une mauvaise façon de procéder.

SAFE est l’ensemble d’autorisations par défaut, mais il est très restrictif.Avec le paramètre SAFE, vous pouvez accéder uniquement aux données d'une base de données locale pour exécuter une logique de calcul sur ces données.EXTERNAL_ACCESS est l'étape suivante dans la hiérarchie des autorisations.Ce paramètre vous permet d'accéder à des ressources externes telles que le système de fichiers, l'Observateur d'événements Windows et les services Web.Ce type d'accès aux ressources n'est pas possible dans SQL Server 2000 et versions antérieures.Cet ensemble d'autorisations restreint également les opérations telles que l'accès au pointeur qui affectent la robustesse de votre assembly.L’ensemble d’autorisations UNSAFE suppose une confiance totale dans l’assembly et n’impose donc aucune limitation de « sécurité d’accès au code ».Ce paramètre est comparable au fonctionnement des procédures stockées étendues : vous supposez que tout le code est sécurisé.Toutefois, ce paramètre limite la création d’assemblys non sécurisés aux utilisateurs disposant des autorisations d’administrateur système.Microsoft vous recommande d'éviter autant que possible de créer des assemblys non sécurisés.

Je continue de croire qu’une procédure CLR pourrait être la meilleure solution.Donc, j'accepte cette réponse.Cependant, soit je ne suis pas très brillant, soit c'est extrêmement difficile à mettre en œuvre.Notre service SQL Server s'exécute sous un compte local car, selon Mircosoft, c'est le seul moyen de faire fonctionner un serveur lié iSeries à partir d'une instance SQL Server 2005 64 bits.Lorsque nous modifions le service SQL Server pour qu'il s'exécute avec un compte de domaine, la commande xp_fileexist fonctionne correctement pour les fichiers situés sur le réseau.

J'ai créé cette procédure stockée CLR, je l'ai construite avec le niveau d'autorisation défini sur Externe et je l'ai signée :

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Security.Principal;

public partial class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void FileExists(SqlString fileName, out SqlInt32 returnValue)
    {
        WindowsImpersonationContext originalContext = null;

        try
        {
            WindowsIdentity callerIdentity = SqlContext.WindowsIdentity;
            originalContext = callerIdentity.Impersonate();

            if (System.IO.File.Exists(Convert.ToString(fileName)))
            {
                returnValue = 1;
            }
            else
            {
                returnValue = 0;
            }
        }
        catch (Exception)
        {
            returnValue = -1;
        }
        finally
        {
            if (originalContext != null)
            {
                originalContext.Undo();
            }
        }
    }
}

Ensuite, j'ai exécuté ces commandes TSQL :

USE master
GO
CREATE ASYMMETRIC KEY FileUtilitiesKey FROM EXECUTABLE FILE = 'J:\FileUtilities.dll' 
CREATE LOGIN CLRLogin FROM ASYMMETRIC KEY FileUtilitiesKey 
GRANT EXTERNAL ACCESS ASSEMBLY TO CLRLogin 
ALTER DATABASE database SET TRUSTWORTHY ON;

Ensuite, j'ai déployé le processus stocké CLR sur ma base de données cible à partir de Visual Studio et j'ai utilisé ce TSQL pour exécuter à partir de SSMS connecté avec l'authentification Windows :

DECLARE @i INT
--EXEC FileExists '\\\\server\\share\\folder\\file.dat', @i OUT
EXEC FileExists 'j:\\file.dat', @i OUT
SELECT @i

Que j'essaie un fichier local ou un fichier réseau, j'obtiens toujours un 0.Je réessayerai peut-être plus tard, mais pour l'instant, je vais essayer d'emprunter une voie différente.Si quelqu'un a un peu de lumière à apporter, ce serait très apprécié.

@Paul, ce code semble devoir fonctionner.Avez-vous essayé de mettre en place un traçage dans cette méthode pour vous assurer Convert.ToString(fileName) n'est-ce pas en quelque sorte arroser le chemin ?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top