sql >> Databasteknik >  >> RDS >> Database

Lagra filer i SQL-databas med FILESTREAM – Del 2

I min tidigare artikel beskrev jag hur man konfigurerar FILESTREAM i SQL Server, skapar FILESTREAM-aktiverad databas och tabeller. Dessutom visade jag hur man infogar och raderar data från FILESTREAM-tabellen.

I den här artikeln kommer jag att demonstrera hur man infogar flera filer i en FILESTREAM-tabell med T-SQL.

I den här demon kommer vi att använda PowerShell-modulen för att fylla i listan med filer och lagra den i SQL-tabellen.

Förutsättningskontroller och användbara frågor för att få FILESTREAM-konfigurationer

För den här demon använder jag:

  1. SQL-version:SQL Server 2017
  2. Databas:FileStream_Demo databas
  3. Verktyg:PowerShell, SQL Server Management Studio, SQL Server Data Tools.

I min tidigare artikel har jag skapat en databas som heter FileStream_Demo . FILESTREAM-funktionen är aktiverad på SQL Server-instans, och databasen har behörigheten T-SQL och Win32 åtkomstnivå.

För att granska inställningarna för FILESTREAMs åtkomstnivå, kör följande fråga:

Använd FileStream_DemoGoSELECT Host_Name() som 'Server Name' , NAME som 'Databas Configuration', CASE WHEN värde =0 DÅ 'FILESTREAM är inaktiverad' NÄR värde =1 DÅ 'Aktiverad för T-SQL' NÄR värde =2 DÅ ' Aktiverad för T-SQL och Win32' AVSLUTA SOM 'FILESTREAM Option'FROM sys.configurationsWHERE NAME ='filströmsåtkomstnivå'Go

Utdata från frågan är som följer:

För att granska databasfiler och plats för FILESTREAM-databehållaren, kör följande fråga:

Använd FileStream_DemoGoSELECT Host_Name() som 'Server Name', NAME Som 'Filegroup Name', type_desc som 'Filegroup Type', Physical_name som 'Databas File Location' FRÅN sys.database_files

Utdata från frågan är som följer:

Infoga flera filer med SQL-skript

Så här infogar du flera filer i en SQL-tabell:

  1. Skapa två SQL-tabeller med namnet Document_List och Document_Content . Document_Content tabellen har FileStreamCol kolumnen med datatypen VARBINARY(MAX) och kolumnattributet FILESTREAM. Innehållet i filerna i katalogen kommer att konverteras i VARBINARY(MAX) och lagras i FileStreamCol kolumnen i Document_Content tabell.
  2. Skapa en dynamisk SQL-fråga som itererar genom Document_Location tabell för att få sökvägen till filer och infoga filer i Document_Content tabeller.
  3. Slå in hela T-SQL-koden i en lagrad procedur.

Skapa SQL-tabeller

Skapa först en global temporär tabell för att lagra information om filerna. För detta, kör följande fråga iFileStream_Demo databas.

ANVÄND [FileStream_Demo]GOCreate tabell Document_List( ID int identity(1,1) Primärnyckel klustrade, fullnamn Varchar(max), namn Varchar(max), attribut Varchar(250), CreationTime datetime, LastAccessTime datetime, LastWriteTime datetime, Längd numerisk(10,2))

Skapa dessutom en tabell för att lagra filerna i tabellen. Kör följande fråga för att skapa en fysisk tabell:

ANVÄND [FileStream_Demo]GOCREATE TABLE [dbo].[Document_Content ]( [ID] [uniqueidentifier] ROWGUIDCOL NOT NULL, [RootDirectory] [varchar](max) NULL, [Filnamn] [varchar](max) NULL, [ FileAttribute] [varchar](150) NULL, [FileCreateDate] [datetime] NULL, [FileSize] [numeric](10, 5) NULL, [FileStreamCol] [varbinary](max) FILESTREAM NULL,UNIQUE ICLUSTERED ( [ID] ASC )MED (PAD_INDEX =AV, STATISTICS_NORECOMPUTE =AV, IGNORE_DUP_KEY =AV, ALLOW_ROW_LOCKS =PÅ, ALLOW_PAGE_LOCKS =PÅ) PÅ [PRIMÄR]) PÅ [PRIMÄR] TEXTIMAGE_ON [PRIMÄRT] [PRIMARY] TEXTIMAGE_ON [PRIMÄRA] 

För att förbättra prestandan för urvalsfrågan, lägg till ett klustrat index på Filnamn och Filtyp kolumner i Document_Content tabell. För detta, exekvera följande kod:

ANVÄND [FileStream_Demo]GOCREATE CLUSTERED INDEX [ICX_Document_Content_FileName] PÅ [dbo].[Document_Content]( [FileName] ASC, [FileType] ASC) MED (PAD_INDEX =OFF, STATISTICS_IN, OFF, STATISTICS_IN, OFF) ONLINE =AV, ALLOW_ROW_LOCKS =PÅ, ALLOW_PAGE_LOCKS =PÅ) PÅ [PRIMÄR] FILESTREAM_ON [Dummy-Documents]GO

Skapa PowerShell-modul för att fylla i filinformation

När tabellerna har skapats kör du PowerShell-skriptet för att infoga detaljer om filer i Document_List tabell. PowerShell-skriptet körs inom den lagrade T-SQL-proceduren, så för att skriva hela koden i SQL-proceduren måste du skapa en PowerShell-funktion. Katalogsökvägen är en obligatorisk indataparameter för funktionen. Skriptet hämtar listan med filer, finns i katalogparametern som används för att köra PowerShell-funktionen.

Koden är följande:

  1. Skapa en funktion och deklarera obligatoriska inmatningsparametrar. Koden är som följer:
    function global:getFileList{param( [Parameter(Position=0,mandatory=$true)] [string[]] $FilePath)
  2. Konstruera en sträng som har en "Infoga"-fråga. Se följande kod:
    [email protected]'INSERT INTO ##Document_List( fullständigt namn, namn, attribut, CreationTime, LastAccessTime, LastWriteTime, Length) VÄRDEN ( '{0}', '{1}', '{ 2}', '{3}', '{4}', '{5}', '{6}')'@
  3. Hämta listan över filer med kommandot Get-ChildItem -Recurse formatera utdata från kommandot. Koden är som följer:
    Get-ChildItem -Recurse $Directorypath | välj @{Label="FullName";Expression={split-path($_.FullName)}}, namn, attribut, CreationTime, LastAccessTime, LastWriteTime,@{Label="Length";Expression={$_.Length / 1MB -som [int] }}
  4. Med hjälp av For-Each-loopen, lagra utdata i Document_content tabell. För att köra frågan på FileStream_Demo databasen använder skriptet Invoke-Sqlcmd . Koden är som följer:
    ForEach-Object { $SQL =$sqltmplt -f $_.FullName, $_.name, $_.attributes, $_.CreationTime, $_.LastAccessTime, $_.LastWriteTime, $_.Length Invoke-sqlcmd -Query $SQL -ServerInstance TTI412-VM\SQL2017 -database FileStream_Demo }

Hela koden för PowerShell-funktionen kommer att se ut som följande:

function global:getFileList{param( [Parameter(Position=0,mandatory=$true)] [string[]] $FilePath)Write-Output "Inserting files"[email protected]'INSERT INTO dbo.Document_List( fullständigt namn, namn, attribut, CreationTime, LastAccessTime, LastWriteTime, Length ) VÄRDEN ( '{0}', '{1}', '{2}', '{3}', '{4}', '{5} ', '{6}')'@Invoke-Sqlcmd -Query "Truncate Table Document_List" -ServerInstance TTI412-VM\SQL2017 -database FileStream_DemoGet-ChildItem -Recurse $FilePath | välj @{Label="FullName";Expression={split-path($_.FullName)}},namn,attribut, CreationTime, LastAccessTime, LastWriteTime,@{Label="Length";Expression={$_.Length / 1MB -as [int] }}| ForEach-Object {$SQL =$sqltmplt -f $_.FullName, $_.name,$_.attributes, $_.CreationTime, $_.LastAccessTime, $_.LastWriteTime,$_.Length Invoke-sqlcmd -Query $SQL -ServerInstance TTI412-VM\SQL2017 -database FileStream_Demo}Skriv-output "Filen har infogats framgångsrikt... Nedan finns en lista med filer."}

För att använda PowerShell-funktionen inom SQL Stored-proceduren måste vi registrera ovanstående skript som PowerShell-modul. För detta skapar du en katalog som hetergetFileListC:\Windows\System32\WindowsPowerShell\v1.0\Modules . För att registrera ett PowerShell-skript som en modul, bör skript- och katalognamnen vara desamma. Spara därför ovanstående skript somgetFileList.psm1 i getFileList katalog.

Nu, när vi körde PowerShell-skriptet från T-SQL, måste vi importera getFileList modul. För detta, lägg till följande kod i PowerShell-profilen. PowerShell-profilen kommer att skapas på C:\Windows\System32\WindowsPowerShell\v1.0 plats.

import-modul getFileList

Om profilen inte finns, kör följande kommando för att skapa en profil.

New-Item -Type File -Path $PROFILE.AllUsersAllHosts -Force

Skapa en lagrad procedur för att importera filer

När vi har lagrat fillistan och informationen i SQL-tabellen kommer vi att infoga filerna i Document_Content bord.

För att göra denna uppgift effektivt, skapa en parameteriserad lagrad procedur med namnet sp_Insert_Documents . Den kommer att använda FileLocation parameter som är av varchar-datatypen. Proceduren fyller i listan med filer från den plats som anges i parametern och infogar alla filer i Document_Content bord.

Steg 1:Ändra konfigurationsparametern.

För att köra PowerShell-kommandot med T-SQL, aktivera xp_cmdshell konfigurationsalternativ. Det är ett avancerat konfigurationsalternativ; därför innan du aktiverar xp_cmdshell , aktiveraVisa avancerat alternativ konfigurationsalternativ. För detta, kör följande T-SQL-kommandon i följd.

använd mastergoexec sp_configure 'visa avancerat alternativ',1omkonfigurera med overrideExec sp_configure 'xp_cmdshell',1Konfigurera om med åsidosättande

Steg 2:Använd PowerShell-skriptet för att fylla i fillistan inom T-SQL-kod

För att köra ett PowerShell-skript med T-SQL, använd xp_cmdshell procedur. Den kör kommandot PowerShell, som fyller i en lista med filer och dess detaljer i Document_List tabell.
Koden är följande:

deklarera @PSScript varchar(2500)set @PSScript='powershell.exe getFileList ''' + @FileLoc +'''' exec xp_cmdshell @PSScript

Steg 3:Skapa en dynamisk SQL-fråga för att få filens plats

Skapa en dynamisk SQL-fråga som itererar genom Document_List tabell, laddar innehållet i filen, som finns på sökvägen som anges i Fullnamn konverterar den till kolumnen VARBINAR(MAX) och infogar den i Document_Content tabell. Tillsammans med fil infogar skriptet filnamn, filattribut, filstorlek och filtyp i Document_Content tabell. Skriptet använder case uttryck för att bestämma filtypen.

Koden är följande:

SET @FileCount =(SELECT Count(*) FROM Document_List) WHILE ( @i <@FileCount ) BÖRJA SET @FileName =(VÄLJ TOP 1-namn FRÅN Document_List) /* Sammanfoga Katalogplats och Filnamn-kolumnen för att generera FQDN. */ SET @FileName =(VÄLJ TOP 1 Namn FRÅN Document_List) SET @FileLocation =(VÄLJ TOP 1 fullnamn FRÅN Document_List där namn=@Filnamn) SET @FileAttribute =(VÄLJ TOP 1 attribut FRÅN Document_List där namn=@Filnamn) SET @ FileCreateDate =(VÄLJ TOP 1 CreationTime FROM Document_List där namn=@Filnamn) SET @FileSize =(VÄLJ TOP 1 Length FROM Document_List där namn=@FileName) SET @FileType =(VÄLJ TOP 1 CASE NÄR (namn LIKE '%jpg%') ) ELLER ( namn LIKE '%png%' ) ELLER ( namn LIKE '%jpg%' ) ELLER (namn LIKE '%bmp%' ) SEDAN 'Bilder' NÄR (namn SOM '%txt%' )SEDAN 'Textfiler' When ( namn LIKE '%xls%' )SÅ 'Textfiler' När (namn LIKE '%doc%' ) DÅ 'Textfiler' ANNARS 'Övriga filer' AVSLUTA SOM 'Filtyp' FRÅN Document_List där namn=@Filnamn) SET @SQLText ='Infoga i Document_Content (ID, RootDirectory, FileName, FileAttribute,FileCreateDate,FileSize,FileType,FileStreamCol) Välj NEWID(), ''' + @File Location + ''', ''' + @Filnamn + ''', ''' + @FileAttribute + ''', ''' + @FileCreateDate + ''', ''' + @FileSize + ''', ' '' + @FileType + ''', bulkColumn från Openrowset(Bulk '''+ @FileLocation + ''', Single_Blob) som tb' EXEC Sp_executesql @SQLText DELETE FROM Document_List WHERE name =@FileName SET @I =@I + 1SLUT

Steg 4:Slå ihop hela SQL-koden i en lagrad procedur

Skapa en parameteriserad lagrad procedur med namnet sp_Insert_Files och slå in koden i den.

Koden för lagrad procedur är följande:

använd FileStream_DemogoCreate Procedur sp_Insert_Files@FileLoc varchar(max)as start DECLARE @FileCount INTDECLARE @I INT =0DECLARE @Filnamn NVARCHAR(max)DECLARE @SQLText NVARCHAR(max)declare @PSFiScript0)Location NCLARE(2) )declare @FileAttribute varchar(50)declare @FileCreateDate varchar(50)declare @FileSize varchar(10)declare @FileType varchar(20)set @PSScript='powershell.exe getFileList ''' + @FileLoc +'''' exec xp_cmdshell @PSScriptSET @FileCount =(SELECT Count(*) FROM Document_List) WHILE ( @i <@FileCount ) BEGIN /* Hämta filnamnet från Document_Name-tabellen */ SET @FileName =(VÄLJ TOP 1-namn FRÅN Document_List) /* Fyll i Fildetaljer från Document_List-tabell*/ SET @FileName =(VÄLJ TOP 1-namn FRÅN Document_List) SET @FileLocation =(VÄLJ TOP 1-fullnamn FRÅN Document_List där namn=@Filnamn) SET @FileAt tribute =(VÄLJ TOP 1 attribut FRÅN Document_List där namn=@Filnamn) SET @FileCreateDate =(VÄLJ TOP 1 CreationTime FROM Document_List där namn=@Filnamn) SET @FileSize =(SELECT TOP 1 Length FROM Document_List där namn=@Filnamn) / *Fastställ typ av fil*/ SET @FileType =(VÄLJ TOP 1 CASE NÄR (namn LIKE '%jpg%') ELLER (namn LIKE '%png%') ELLER (namn LIKE '%jpg%') ELLER (namn LIKE '%bmp%' ) SEN 'Bilder' NÄR (namn SOM '%txt%' )SEDAN 'Textfiler' När (namn SOM '%xls%' )SÅ 'Textfiler' När (namn SOM '%doc%') DÅ 'Textfiler' ANNARS 'Övriga filer' SLUTAR SOM 'Filtyp' FRÅN Document_List där namn=@Filnamn) SET @SQLText ='Infoga i Document_Content (ID, RootDirectory, FileName, FileAtt ribute,FileCreateDate,FileSize,FileType,FileStreamCol) Välj NEWID(), ''' + @FileLocation + ''', ''' + @FileName + ''', ''' + @FileAttribute + ''', '' ' + @FileCreateDate + ''', ''' + @FileSize + ''', ''' + @FileType + ''', bulkColumn från Openrowset(Bulk '''+ @FileLocation + ''', Single_Blob) som tb' EXEC Sp_executesql @SQLText DELETE FROM Document_List WHERE name =@Filnamn SET @I =@I + 1ENDend

Infoga filer med hjälp av lagrad procedur

Testa nu den lagrade proceduren. Jag har lagt till några filer i E:\Files katalog. Infoga filerna i SQL-tabellen genom att utföra den lagrade proceduren. Koden är följande:

använd FileStream_Demogoexec sp_Insert_Files 'E:\Files'

Låt oss verifiera att filerna har kopierats till tabellen. För detta, exekvera följande kod:

välj RootDirectory som 'Filplats', Filnamn som 'Filnamn', FileAttribute som 'Attribute', FileCreateDate som 'Attribut', FileSize som 'Filstorlek', FileType som 'Filtyp', FileStreamCol som 'Filinnehåll' från Document_Content där FileType='Bilder'

Utdata från frågan är som följer:

För att komma åt filen i FILESTREAM-dataarkivet med Win32 API, använd Sökväg () metoden för FILESTREAM. Med Sökvägsnamn () metod, kan vi identifiera den logiska sökvägen för att identifiera filen i FILESTREAMs datalager unikt.

Koden är följande:

välj RootDirectory som 'Filplats', Filnamn som 'Filnamn', FileAttribute som 'Attribute', FileCreateDate som 'Attribut', FileSize som 'Filstorlek', FileType som 'Filtyp', FileStreamCol.PathName() AS FilePathfrom Document_Content där FileName='RowDesign.png'

Utdata från frågan är som följer:

Låt oss navigera till FILESTREAM-databehållaren (E:\Dummy-Documents) för att verifiera att filerna har infogats. Se följande skärmdump:

Som du kan se har alla filer infogats i SQL-tabeller och FileStream-behållaren.

Sammanfattning

I den här artikeln har jag täckt:

  1. Användbar fråga för att verifiera förutsättningarna för FILESTREAM-funktionen.
  2. Hur man registrerar en PowerShell-funktion som en modul.
  3. Förklara PowerShell-koden för att infoga fillistan i SQL-tabellen med hjälp av PowerShell-skriptet.
  4. Förklarade koden för lagrad procedur för att infoga flera filer i SQL-tabellen.
  5. Användbara frågor för att samla en lista över dokument, lagrade i FILESTREAM-behållare.

I framtida artiklar kommer jag att förklara hur man säkerhetskopierar och återställer FILESTREAM-aktiverad databas.

Håll ögonen öppna!


  1. Hur TIME_FORMAT() fungerar i MariaDB

  2. Postgres-anslutningen har stängts fel i Spring Boot

  3. Hur man ansluter till SQL-serverdatabas från en Windows 10 UWP-app

  4. Exportera tabelldata från en SQL Server till en annan