Qual è il metodo migliore per verificare se esiste un file da una procedura memorizzata di SQL Server 2005?

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

  •  08-06-2019
  •  | 
  •  

Domanda

Abbiamo utilizzato per anni la procedura memorizzata xp_fileexist "non documentata" in SQL Server 2000 e non abbiamo avuto problemi con essa.Nel 2005, sembra che abbiano leggermente modificato il comportamento per restituire sempre uno 0 se l'account utente in esecuzione non è un amministratore di sistema.Sembra inoltre restituire uno zero se il servizio SQL Server è in esecuzione con l'account LocalSystem e si sta tentando di controllare un file sulla rete.

Mi piacerebbe allontanarmi da xp_fileexist.Qualcuno ha un modo migliore per verificare l'esistenza di un file in un percorso di rete dall'interno di una procedura memorizzata?

È stato utile?

Soluzione

Forse una procedura memorizzata CLR è ciò che stai cercando.Questi vengono generalmente utilizzati quando è necessario interagire in qualche modo con il sistema.

Altri suggerimenti

Dovrai contrassegnare CLR come EXTERNAL_ACCESS per ottenere l'accesso allo spazio dei nomi System.IO, tuttavia, per come vanno le cose, non è un brutto modo di farlo.

SAFE è il set di autorizzazioni predefinito, ma è altamente restrittivo.Con l'impostazione SAFE, puoi accedere solo ai dati di un database locale per eseguire la logica di calcolo su tali dati.EXTERNAL_ACCESS è il passaggio successivo nella gerarchia delle autorizzazioni.Questa impostazione consente di accedere a risorse esterne come file system, Visualizzatore eventi di Windows e servizi Web.Questo tipo di accesso alle risorse non è possibile in SQL Server 2000 e versioni precedenti.Questo set di autorizzazioni limita inoltre operazioni come l'accesso al puntatore che influiscono sulla robustezza dell'assembly.Il set di autorizzazioni UNSAFE presuppone l'attendibilità totale dell'assembly e pertanto non impone limitazioni di "protezione dall'accesso di codice".Questa impostazione è paragonabile al funzionamento delle procedure memorizzate estese: si presuppone che tutto il codice sia sicuro.Tuttavia, questa impostazione limita la creazione di assembly non sicuri agli utenti che dispongono di autorizzazioni di amministratore di sistema.Microsoft consiglia di evitare quanto più possibile la creazione di assembly non sicuri.

Continuo a credere che una procedura CLR potrebbe essere la soluzione migliore.Quindi accetto questa risposta.Tuttavia, o non sono così brillante o è estremamente difficile da implementare.Il nostro servizio SQL Server viene eseguito con un account locale perché, secondo Mircosoft, questo è l'unico modo per far funzionare un server collegato iSeries da un'istanza di SQL Server 2005 a 64 bit.Quando modifichiamo il servizio SQL Server per l'esecuzione con un account di dominio, il comando xp_fileexist funziona correttamente per i file che si trovano sulla rete.

Ho creato questa procedura memorizzata CLR e l'ho creata con il livello di autorizzazione impostato su Esterno e l'ho firmata:

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();
            }
        }
    }
}

Quindi ho eseguito questi comandi 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;

Quindi ho distribuito la procedura memorizzata CLR nel mio database di destinazione da Visual Studio e ho utilizzato questo TSQL per eseguire da SSMS effettuato l'accesso con l'autenticazione di Windows:

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

Sia che provo un file locale o un file di rete, ottengo sempre uno 0.Potrei riprovarci più tardi, ma per ora proverò a percorrere una strada diversa.Se qualcuno avesse un po' di luce da fare, sarebbe molto apprezzato.

@Paul, quel codice sembra che dovrebbe funzionare.Hai provato a inserire qualche traccia in quel metodo per essere sicuro Convert.ToString(fileName) non sta in qualche modo bagnando il percorso?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top