2016-04-14 19 views
3

私は最近、画像をテーブルに挿入するのにOPENROWSETを使い始めました。以前、私はそれぞれの画像(1枚の画像= 1巻のINSERT書)へのパスを指定して、画像のバイナリ文字列を生成するためにPHPを使用します。しかし、私は単一のクエリですべての画像を挿入しようとしていますOPENROWSETでテーブルに格納されたパスを使用するにはどうすればよいですか?

INSERT INTO nopCommerce..Picture (PictureBinary, MimeType, SeoFilename, AltAttribute, TitleAttribute, IsNew) 
VALUES (
    (
     SELECT * 
     FROM OPENROWSET(BULK '" . $this->image['path'] . "', SINGLE_BLOB) AS Binary 
    ), 
    '" . $this->image['mime_type'] . "', 
    '" . $this->image['seo_filename'] . "', 
    '" . $this->image['alt'] . "', 
    '', 
    0 
) 

。だから、私は各イメージへのパスをテーブルに格納し始めました。そして、以前は(PHPの文字列の代わりにテーブルのパスフィールドを使用するだけで)それぞれを挿入する必要があります。私は次のことをしようとすると、しかし、:

INSERT INTO nopCommerce..Picture (PictureBinary, MimeType, SeoFilename, AltAttribute, TitleAttribute, IsNew) 
SELECT 
    (
     SELECT * 
     FROM OPENROWSET(BULK ImagePath, SINGLE_BLOB) AS Binary 
    ), 
    MimeType, 
    Name, 
    Alt, 
    '', 
    0 
FROM nopRMS..Product_Image_Mappings 

私は、次のエラーが表示さ:だから

Msg 102, Level 15, State 1, Line 5
Incorrect syntax near 'ImagePath'.

を、私は(無駄に)列の名前の前後に引用符を追加してみました:

INSERT INTO nopCommerce..Picture (PictureBinary, MimeType, SeoFilename, AltAttribute, TitleAttribute, IsNew) 
SELECT 
    (
     SELECT * 
     FROM OPENROWSET(BULK 'ImagePath', SINGLE_BLOB) AS Binary 
    ), 
    MimeType, 
    Name, 
    Alt, 
    '', 
    0 
FROM nopRMS..Product_Image_Mappings 

Msg 4860, Level 16, State 1, Line 1
Cannot bulk load. The file "ImagePath" does not exist.

これを達成する方法があるに違いありません、私はどこでも正しい構文を見つけることができません。誰でもSQL Serverにパス(文字列)を取得する方法を知っていますか?dbo.Product_Image_Mappings.ImagePath

UPDATE
私はあなたにdbo.Product_Image_Mappings.ImagePathが戻ってくることを値の例を与えることを忘れていました。それは\\DEREK\WebImages\1\ca-82300.jpgのようなパス...

UPDATE
だEirikur Eirikssonがthis threadにソリューションを提供しているように見えるが、これは、同じ目的を達成する過度に複雑な方法のように見える...

UPDATE(Eirikur Eirikssonのメソッドを使用しようとしました)

DECLARE @SQL_STR NVARCHAR(MAX) = N''; 

SELECT @SQL_STR = STUFF(
    (
     SELECT 
      N' 
      UNION ALL 
      SELECT ' 
      + N'(SELECT X.BulkColumn FROM OPENROWSET(BULK ' 
      + NCHAR(39) + im.ImagePath + NCHAR(39) 
      + N', SINGLE_BLOB) AS X) AS PictureBinary,' 
      + NCHAR(39) + im.MimeType + NCHAR(39) 
      + N' AS MimeType,' 
      + NCHAR(39) + im.Name + NCHAR(39) 
      + N' AS SeoFilename,' 
      + NCHAR(39) + REPLACE(im.Alt, '''', '''''') + NCHAR(39) 
      + N' AS AltAttribute,' 
      + N'NULL AS TitleAttribute,' 
      + N'0 AS IsNew' 
     FROM nopRMS..Product_Image_Mappings im 
     FOR XML PATH(''), TYPE 
    ).value('.[1]','NVARCHAR(MAX)'),1,12,N'' 
) 

INSERT INTO nopCommerce..Picture (PictureBinary, MimeType, SeoFilename, AltAttribute, TitleAttribute, IsNew) 
EXEC (@SQL_STR); 

これちょっと働いていたが、それはわずか42行(7200 +のうち)に挿入...私はトンを必要とします私はこのクエリについて何かを変更する必要があるかもしれないが、私はそれについて何も知らない(基本的なINSERT、SELECTなどを除いて)

+0

また、この挿入ステートメントをマージステートメント内で使用していることにも言及しておきます。私はこれも私のオプションを制限するかもしれないと信じている(ダイナミックSQLが唯一のオプションだと思うので、私は 'TARGETでマッチしないときにダイナミックSQLを実行できるとは思っていない。) – derekmx271

+0

FYI: 「SSCertifiable」という用語は名前ではなく、サイトへのポイントおよび/またはログインの数に関するラベルです。 。 –

+0

最初のコードサンプルでPHPコードを使用していますが、PHPページ内にSQLを構築して実行していますか?すべてのレコードに対して完全な動的文字列を指定して実行しますが、遅くなります –

答えて

1

多分、 OPENROWSETを使用しますか?あなたが望んでいるものは、SQLCLRを使用してはるかに簡単できれいな方法で処理することができます。 Scalar UDFを作成してファイルの内容を読み込み、それをVARBINARY(MAX)として返すことができます。その後、既存のクエリにうまく収まります。例:

INSERT INTO nopCommerce.dbo.Picture (PictureBinary, MimeType, SeoFilename, 
         AltAttribute, TitleAttribute, IsNew) 
SELECT 
    dbo.GetBinaryFile([ImagePath]) AS [PictureBinary], 
    MimeType, 
    Name, 
    Alt, 
    '', 
    0 
FROM nopRMS.dbo.Product_Image_Mappings; 

dbo.GetBinaryFile()のコードはどのくらいですか?ここでは、次のとおりです。

using System; 
using System.Data.SqlTypes; 
using System.IO; 
using Microsoft.SqlServer.Server; 

[return:SqlFacet(MaxSize = -1)] 
[SqlFunction(IsDeterministic = false, IsPrecise = true)] 
public static SqlBytes GetBinaryFile([SqlFacet(MaxSize = 1000)] SqlString FilePath) 
{ 
    if (FilePath.Value.Trim().Equals(String.Empty)) 
    { 
     return SqlBytes.Null; 
    } 

    return new SqlBytes(File.ReadAllBytes(FilePath.Value)); 
} 

そして、T-SQLラッパーオブジェクト

は以下の通り( NULLが渡された場合、それは、C#のコードで FilePath.IsNullをチェックするので、必要に実行をスキップしないよう WITH RETURNS NULL ON NULL INPUTラインに注意してください。 - )

CREATE FUNCTION [dbo].[GetBinaryFile](@FilePath NVARCHAR(1000)) 
RETURNS VARBINARY(MAX) 
WITH RETURNS NULL ON NULL INPUT 
AS 
EXTERNAL NAME [CSVParser].[CSVUtils].[GetBinaryFile]; 

アセンブリには、WITH PERMISSION_SET = EXTERNAL_ACCESSとマークする必要があります。これを達成するために多くの人々がTRUSTWORTHYのデータベースプロパティをONに設定する簡単なルートを辿りますが、それはセキュリティリスクであり、必要でもありません。ただ、次の手順を実行してOFFTRUSTWORTHYセットを維持しながら、あなたはEXTERNAL_ACCESSにアセンブリを設定することができます。

  1. ログインアセンブリ。
  2. そのDLLからmasterの非対称キーを作成します。
  3. その非対称キーからログインを(masterにも)作成します。
  4. 新しいログインにEXTERNAL ACCESS ASSEMBLY権限を与えます。あなたは、私が書いた以下の記事でのVisual Studio/SSDT(SQL Serverデータツール)でこれを行う方法の詳細な手順を見つけることができます

Stairway to SQLCLR Level 7: Development and Security(そのサイトがコンテンツを視聴するためには無料登録が必要です) 。

SQL#ライブラリの完全版(これは私が作成したものですが、多くの機能は以下のとおりです)でも同様の機能が利用できます(無料ではありませんが)。無料、ファイル_ *ファイルシステムの機能はフルバージョンのみ)。

+0

これはうまくいくかもしれません:)私はこのアセンブリを構築し、試してみます。これありがとう! – derekmx271

関連する問題