Qual é o melhor método para verificar se existe um arquivo de um procedimento armazenado do SQL Server 2005?

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

  •  08-06-2019
  •  | 
  •  

Pergunta

Usamos o procedimento armazenado xp_fileexist "não documentado" por anos no SQL Server 2000 e não tivemos problemas com ele.Em 2005, parece que eles modificaram ligeiramente o comportamento para sempre retornar 0 se a conta do usuário em execução não for um administrador de sistema.Também parece retornar zero se o serviço SQL Server estiver sendo executado na conta LocalSystem e você estiver tentando verificar um arquivo na rede.

Eu gostaria de fugir do xp_fileexist.Alguém tem uma maneira melhor de verificar a existência de um arquivo em um local de rede dentro de um procedimento armazenado?

Foi útil?

Solução

Talvez um procedimento armazenado CLR seja o que você está procurando.Geralmente são usados ​​​​quando você precisa interagir de alguma forma com o sistema.

Outras dicas

Você terá que marcar o CLR como EXTERNAL_ACCESS para obter acesso ao namespace System.IO, no entanto, do jeito que as coisas vão, essa não é uma maneira ruim de fazer isso.

SAFE é o conjunto de permissões padrão, mas é altamente restritivo.Com a configuração SAFE, você pode acessar apenas dados de um banco de dados local para executar lógica computacional nesses dados.EXTERNAL_ACCESS é a próxima etapa na hierarquia de permissões.Essa configuração permite acessar recursos externos, como sistema de arquivos, Visualizador de eventos do Windows e serviços Web.Esse tipo de acesso a recursos não é possível no SQL Server 2000 e versões anteriores.Esse conjunto de permissões também restringe operações como acesso de ponteiro que afetam a robustez do seu assembly.O conjunto de permissões UNSAFE assume total confiança do assembly e, portanto, não impõe limitações de "Segurança de acesso ao código".Essa configuração é comparável à maneira como os procedimentos armazenados estendidos funcionam – você assume que todo o código é seguro.No entanto, essa configuração restringe a criação de assemblies inseguros a usuários que tenham permissões de administrador de sistema.A Microsoft recomenda que você evite ao máximo criar assemblies inseguros.

Ainda acredito que um procedimento CLR pode ser a melhor aposta.Então, estou aceitando essa resposta.No entanto, ou não sou tão inteligente ou é extremamente difícil de implementar.Nosso serviço SQL Server está sendo executado em uma conta local porque, de acordo com a Mircosoft, essa é a única maneira de fazer com que um servidor vinculado do iSeries funcione a partir de uma instância do SQL Server 2005 de 64 bits.Quando alteramos o serviço SQL Server para ser executado com uma conta de domínio, o comando xp_fileexist funciona bem para arquivos localizados na rede.

Eu criei este procedimento armazenado CLR e construí-o com o nível de permissão definido como Externo e assinei-o:

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

Então executei estes comandos 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;

Em seguida, implantei o proc armazenado CLR em meu banco de dados de destino do Visual Studio e usei este TSQL para executar a partir do SSMS conectado com autenticação do Windows:

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

Quer eu tente um arquivo local ou um arquivo de rede, sempre obtenho 0.Posso tentar novamente mais tarde, mas por enquanto vou tentar seguir um caminho diferente.Se alguém tiver alguma luz para lançar, ficaria muito grato.

@Paul, esse código parece que deveria funcionar.Você já tentou colocar algum rastreamento nesse método para ter certeza Convert.ToString(fileName) não é de alguma forma limpar o caminho?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top