2016-04-14 32 views
3

Ich habe gerade begonnen, OPENROWSET zu verwenden, um Bilder in eine Tabelle einzufügen. Früher habe ich den Pfad zu jedem Bild angeben (1 Bild = 1 INSERT-Anweisung), und verwenden Sie PHP das Image des Binärkette zu erzeugen:Wie verwende ich einen Pfad in der Tabelle mit 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 
) 

aber ich versuche, alle Bilder mit einer einzigen Abfrage einzufügen. Also habe ich begonnen, den Pfad zu jedem Bild in einer Tabelle zu speichern, und jetzt muss ich jeden Pfad wie zuvor einfügen (nur mit dem Pfadfeld der Tabelle anstelle einer PHP-Zeichenfolge). Aber, wenn ich folgendes versuchen:

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 

Ich erhalte den folgenden Fehler:

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

Also habe ich versucht, Anführungszeichen um die Spaltennamen hinzugefügt wird (ohne Erfolg):

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.

Es muss einen Weg geben, dies zu erreichen, ich kann nirgends die richtige Syntax online finden. Kann jemand SQL Server sagen, um den Pfad (Zeichenfolge) von dbo.Product_Image_Mappings.ImagePath zu erhalten?

UPDATE
ich vergessen hat, ein Beispiel für einen Wert zu geben, dass dbo.Product_Image_Mappings.ImagePath zurückkehren würde. Es ist Pfade wie \\DEREK\WebImages\1\ca-82300.jpg ...

UPDATE
Es scheint, dass Eirikur Eiriksson eine Lösung in this thread zur Verfügung gestellt hat, aber das sieht aus wie ein übermäßig komplizierte Verfahren zu deren Ende zu erreichen ...

UPDATE (Versuch mit Eirikur Eiriksson-Methode)

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

Diese irgendwie funktioniert, aber es eingefügt nur 42 Zeilen (aus 7200 +) ... ich brauche t sein 100% genau zu sein :(Ich gebe zwar zu, muss ich vielleicht etwas über diese Abfrage ändern, aber ich weiß nichts darüber (abgesehen von der grundlegenden INSERT, SELECT, etc.)

+0

Ich sollte auch erwähnen, dass ich diese Insert-Anweisung innerhalb einer Merge-Anweisung verwenden. Ich glaube, dass dies auch meine Optionen einschränken kann (weil es so aussieht, als wäre Dynamic SQL die einzige Option, und ich glaube nicht, dass ich Dynamic SQL innerhalb von "WENN NICHT GEMEINSAM DURCH TARGET" ausführen kann. – derekmx271

+0

FYI: Ich habe die Formatierung aktualisiert ein wenig in der Frage, aber auch der Name der Person, die diesen Code auf dem SQL Server Central-Forum geschrieben hat Der Begriff "SSCertifiable" ist kein Name, sondern ein Label, das mit wie vielen Punkten und/oder Logins auf der Website verknüpft ist –

+0

Sie haben PHP-Code in Ihrem ersten Codebeispiel.Sie bauen SQL innerhalb einer PHP-Seite und führen es aus? Es ist wichtig zu wissen. Ihr zweiter Code-Versuch (mit 'ImagePath') könnte mit einem Cursor erreicht werden - ein Cursor baut die vollständige dynamische Zeichenfolge für jeden Datensatz und führt es aus, aber es wäre langsam –

Antwort

1

Vielleicht nicht t verwenden OPENROWSET? Was Sie wollen, kann mit SQLCLR viel einfacher und sauberer behandelt werden. Sie können eine benutzerdefinierte Skalarfunktion erstellen, um nur den Inhalt einer Datei zu lesen und diesen als VARBINARY(MAX) zurückzugeben. Dann passt es gut zu Ihrer bestehenden Anfrage. Zum Beispiel:

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; 

Und wie viel Code dauert es dbo.GetBinaryFile()? Hier ist sie:

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

Und das T-SQL-Wrapper-Objekt ist die folgende (bitte beachten Sie die WITH RETURNS NULL ON NULL INPUT Linie, wie es die Ausführung überspringt, wenn NULL in übergeben wird, also keine Notwendigkeit für FilePath.IsNull im C# -Code zu überprüfen: -

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

Die Versammlung muss als WITH PERMISSION_SET = EXTERNAL_ACCESS markiert werden.Viele Leute gehen den einfachen Weg, die Datenbankeigenschaft von TRUSTWORTHY auf ON zu setzen, um dies zu erreichen, aber das ist ein Sicherheitsrisiko und ist nicht einmal notwendig. Nur Sie wie folgt und Sie können die Versammlung EXTERNAL_ACCESS gesetzt, während TRUSTWORTHY Set OFF halten:

  1. Zeichen der Versammlung.
  2. Erstellen Sie einen asymmetrischen Schlüssel in master von dieser DLL.
  3. Erstellen Sie eine Anmeldung (auch in master) von diesem asymmetrischen Schlüssel.
  4. Gewähren Sie die neue Anmeldung die EXTERNAL ACCESS ASSEMBLY Erlaubnis.

Sie können detaillierte Anleitung, wie dies in Visual Studio/SSDT (SQL Server-Datentool) in dem folgenden Artikel zu tun, die ich schrieb: Stairway to SQLCLR Level 7: Development and Security (diese Website hat kostenlose Registrierung erfordern, um den Inhalt zu anzeigen) .

Auch für jeden, der sich nicht mit der Erstellung/Bereitstellung der Assembly beschäftigen möchte, ist eine ähnliche Funktion in der Vollversion der SQL# Bibliothek (die ich erstellt habe und während viele Funktionen sind) verfügbar (wenn auch nicht kostenlos) frei, die File_ * Dateisystemfunktionen sind nur in der Vollversion).

+0

Das könnte funktionieren :) Ich werde diese Baugruppe bauen und es ausprobieren. Danke dafür! – derekmx271

Verwandte Themen