4

「文書化されていない」xp_fileexist ストアド プロシージャを SQL Server 2000 で何年も使用しましたが、問題はありませんでした。2005 年に、実行中のユーザー アカウントが sysadmin でない場合は常に 0 を返すように動作がわずかに変更されたようです。SQL Server サービスが LocalSystem アカウントで実行されていて、ネットワーク上のファイルをチェックしようとしている場合にも、ゼロが返されるようです。

xp_fileexist から離れたいです。ストアド プロシージャ内からネットワーク上の場所にファイルが存在するかどうかを確認するより良い方法はありますか?

4

3 に答える 3

5

System.IO 名前空間にアクセスするには、CLR を EXTERNAL_ACCESS としてマークする必要がありますが、これは悪い方法ではありません。

SAFE は既定のアクセス許可セットですが、非常に制限的です。SAFE 設定を使用すると、ローカル データベースのデータのみにアクセスして、そのデータに対して計算ロジックを実行できます。EXTERNAL_ACCESS は、権限階層の次のステップです。この設定により、ファイル システム、Windows イベント ビューア、Web サービスなどの外部リソースにアクセスできます。この種類のリソース アクセスは、SQL Server 2000 以前では不可能です。このアクセス許可セットは、アセンブリの堅牢性に影響を与えるポインター アクセスなどの操作も制限します。UNSAFE アクセス許可セットは、アセンブリの完全な信頼を想定しているため、「コード アクセス セキュリティ」の制限はありません。この設定は、拡張ストアド プロシージャが機能する方法に匹敵します。つまり、すべてのコードが安全であると仮定します。でも、この設定は、安全でないアセンブリの作成を sysadmin 権限を持つユーザーに制限します。安全でないアセンブリをできるだけ作成しないようにすることをお勧めします。

于 2008-08-19T18:47:21.970 に答える
4

探しているのは CLR ストアド プロシージャかもしれません。これらは通常、何らかの方法でシステムと対話する必要がある場合に使用されます。

于 2008-08-19T18:13:13.040 に答える
3

私は今でも、CLR プロシージャが最善の策であると信じています。だから、私はその答えを受け入れています。しかし、私はそれほど頭が良くないか、実装が非常に困難です。Mircosoft によれば、64 ビット SQL Server 2005 インスタンスから iSeries リンク サーバーを動作させる唯一の方法であるため、SQL Server サービスはローカル アカウントで実行されています。ドメイン アカウントで実行するように SQL Server サービスを変更すると、ネットワーク上にあるファイルに対して xp_fileexist コマンドが正常に機能します。

この CLR ストアド プロシージャを作成し、アクセス許可レベルを [外部] に設定してビルドし、署名しました。

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

次に、次の 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;

次に、CLR ストアド プロシージャを Visual Studio からターゲット データベースにデプロイし、この TSQL を使用して、Windows 認証でログインした SSMS から実行しました。

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

ローカル ファイルとネットワーク ファイルのどちらを試しても、常に 0 になります。後でもう一度試すかもしれませんが、今のところ、別の道をたどってみます。誰かが光を当てることができれば、それは大歓迎です。

于 2008-08-20T13:52:21.633 に答える