sql >> Database teknologi >  >> RDS >> Database

Lagring af filer i SQL-database ved hjælp af FILESTREAM – Del 2

I min tidligere artikel beskrev jeg, hvordan man konfigurerer FILESTREAM i SQL Server, opretter FILESTREAM-aktiveret database og tabeller. Desuden demonstrerede jeg, hvordan man indsætter og sletter data fra FILESTREAM-tabellen.

I denne artikel skal jeg demonstrere, hvordan man indsætter flere filer i en FILESTREAM-tabel ved hjælp af T-SQL.

I denne demo skal vi bruge PowerShell-modulet til at udfylde listen over filer og gemme den i SQL-tabellen.

Forudsætningskontrol og nyttige forespørgsler for at få FILESTREAM-konfigurationer

Til denne demo bruger jeg:

  1. SQL-version:SQL Server 2017
  2. Database:FileStream_Demo database
  3. Værktøjer:PowerShell, SQL Server Management Studio, SQL Server Data Tools.

I min tidligere artikel har jeg oprettet en database ved navn FileStream_Demo . FILESTREAM-funktionen er aktiveret på SQL Server-instansen, og databasen har adgangsniveauet T-SQL og Win32.

For at gennemgå indstillingerne for FILESTREAM adgangsniveau skal du udføre følgende forespørgsel:

Brug FileStream_DemoGoSELECT Host_Name() som 'Server Name', NAME som 'Database Configuration', CASE WHEN værdi =0 SÅ 'FILESTREAM er deaktiveret' NÅR værdi =1 SÅ 'Aktiveret for T-SQL' NÅR værdi =2 SÅ ' Aktiveret for T-SQL og Win32' SLUT SOM 'FILESTREAM Option'FROM sys.configurationsWHERE NAME ='filstream-adgangsniveau'Go

Outputtet af forespørgslen er som følger:

For at gennemgå databasefiler og placering af FILESTREAM-databeholderen skal du udføre følgende forespørgsel:

Brug FileStream_DemoGoSELECT Host_Name() som 'Server Name', NAME Som 'Filegroup Name', type_desc som 'Filegroup Type', fysisk_navn som 'Database File Location' FRA sys.database_files

Outputtet af forespørgslen er som følger:

Indsæt flere filer ved hjælp af SQL-script

Sådan indsætter du flere filer i en SQL-tabel:

  1. Opret to SQL-tabeller med navnet Document_List og Document_Content . Document_Content tabellen har FileStreamCol kolonne med datatypen VARBINARY(MAX) og kolonneattributten FILESTREAM. Indholdet af filer i mappen vil blive konverteret i VARBINARY(MAX) og gemt i FileStreamCol kolonne i Document_Content tabel.
  2. Opret en dynamisk SQL-forespørgsel, der itererer gennem Document_Location tabel for at få stien til filer og indsætte filer i Document_Content tabeller.
  3. Indpak hele T-SQL-koden i en lagret procedure.

Opret SQL-tabeller

For det første skal du oprette en global midlertidig tabel for at gemme detaljerne i filerne. Til dette skal du udføre følgende forespørgsel iFileStream_Demo database.

BRUG [FileStream_Demo]GOCreate table Document_List( ID int identity(1,1) Primary Key clustered, fuldnavn Varchar(max), navn Varchar(max), attributter Varchar(250), CreationTime datetime, LastAccessTime datetime, LastWriteTime datetime, Længde numerisk(10,2))

Desuden skal du oprette en tabel for at gemme filerne i tabellen. Udfør følgende forespørgsel for at oprette en fysisk tabel:

BRUG [FileStream_Demo]GOCREATE TABLE [dbo].[Document_Content ]( [ID] [uniqueidentifier] ROWGUIDCOL NOT NULL, [RootDirectory] [varchar](max) NULL, [Filnavn] [varchar](max) NULL, [ FileAttribute] [varchar](150) NULL, [FileCreateDate] [datetime] NULL, [FileSize] [numeric](10, 5) NULL, [FileStreamCol] [varbinary](maks.) FILESTREAM NULL,UNIKK IKKE-KLUNGERET ( [ID] ASC. )MED (PAD_INDEX =FRA, STATISTICS_NORECOMPUTE =FRA, IGNORE_DUP_KEY =FRA, ALLOW_ROW_LOCKS =TIL, ALLOW_PAGE_LOCKS =TIL) PÅ [PRIMÆR]) PÅ [PRIMÆR] TEXTIMAGE_ON [PRIMARY] [PRIMARY] TEXTIMAGE_ON [PRIMARY_> 

For at forbedre ydeevnen af ​​den valgte forespørgsel skal du tilføje et klynget indeks på Filnavn og Filtype kolonner i Document_Content bord. Til dette skal du udføre følgende kode:

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

Opret PowerShell-modul for at udfylde filoplysninger

Når tabellerne er oprettet, skal du udføre PowerShell-scriptet for at indsætte detaljer om filer i Document_List bord. PowerShell-scriptet kører inden for den lagrede T-SQL-procedure, og for at skrive hele koden i SQL-proceduren skal du derfor oprette en PowerShell-funktion. Biblioteksstien er en obligatorisk inputparameter for funktionen. Scriptet henter listen over filer, ligger i mappeparameteren, der bruges til at udføre PowerShell-funktionen.

Koden er som følger:

  1. Opret en funktion og erklær obligatoriske inputparametre. Koden er som følger:
    function global:getFileList{param( [Parameter(Position=0,mandatory=$true)] [string[]] $FilePath)
  2. Konstruer en streng, der har en "Indsæt"-forespørgsel. Se følgende kode:
    [email protected]'INSERT INTO ##Document_List( fuldt navn, navn, attributter, CreationTime, LastAccessTime, LastWriteTime, Length) VALUES ( '{0}', '{1}', '{ 2}', '{3}', '{4}', '{5}', '{6}')'@
  3. Hent listen over filer ved hjælp af kommandoen Get-ChildItem -Recurse formater kommandoens output. Koden er som følger:
    Get-ChildItem -Recurse $Directorypath | vælg @{Label="FullName";Expression={split-path($_.FullName)}}, navn, attributter, CreationTime, LastAccessTime, LastWriteTime,@{Label="Length";Expression={$_.Length / 1MB -som [int] }}
  4. Ved brug af For-Each-løkken skal du gemme outputtet i Document_content bord. For at køre forespørgslen på FileStream_Demo databasen, bruger scriptet Invoke-Sqlcmd . Koden er som følger:
    ForEach-Object { $SQL =$sqltmplt -f $_.FullName, $_.name, $_.attributes, $_.CreationTime, $_.LastAccessTime, $_.LastWriteTime, $_.Length Invoke-sqlcmd -Query $SQL -ServerInstance TTI412-VM\SQL2017 -database FileStream_Demo }

Hele koden for PowerShell-funktionen vil se sådan ud:

function global:getFileList{param( [Parameter(Position=0,mandatory=$true)] [string[]] $FilePath)Write-Output "Inserting files"[email protected]'INSERT INTO dbo.Document_List( fulde navn, navn, attributter, CreationTime, LastAccessTime, LastWriteTime, Length ) VÆRDIER ( '{0}', '{1}', '{2}', '{3}', '{4}', '{5} ', '{6}')'@Invoke-Sqlcmd -Forespørgsel "Truncate Table Document_List" -ServerInstance TTI412-VM\SQL2017 -database FileStream_DemoGet-ChildItem -Recurse $FilePath | vælg @{Label="FullName";Expression={split-path($_.FullName)}},navn,attributter, 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}Skrive-output "Fil indsat med succes... Nedenfor er en liste over filer."}

For at bruge PowerShell-funktionen i SQL Stored-proceduren skal vi registrere ovenstående script som PowerShell-modul. Til dette skal du oprette en mappe med navnetgetFileListC:\Windows\System32\WindowsPowerShell\v1.0\Modules . For at registrere et PowerShell-script som et modul, skal script- og mappenavnene være de samme. Gem derfor ovenstående script somgetFileList.psm1 i getFileList bibliotek.

Nu, da vi udførte PowerShell-scriptet fra T-SQL, skal vi importere getFileList modul. Til dette skal du tilføje følgende kode i PowerShell-profilen. PowerShell-profilen oprettes på C:\Windows\System32\WindowsPowerShell\v1.0 placering.

import-modul getFileList

Hvis profilen ikke eksisterer, skal du udføre følgende kommando for at oprette en profil.

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

Opret en lagret procedure til at importere filer

Når vi gemmer fillisten og oplysningerne i SQL Table, indsætter vi filerne i Document_Content tabel.

For at udføre denne opgave effektivt skal du oprette en parameteriseret lagret procedure med navnet sp_Insert_Documents . Det vil bruge Filplacering parameter, der er af varchar-datatypen. Proceduren udfylder listen over filer fra den placering, der er angivet i parameteren og indsætter alle filerne i Document_Content tabel.

Trin 1:Skift konfigurationsparameteren.

For at køre PowerShell-kommandoen ved hjælp af T-SQL skal du aktivere xp_cmdshell konfigurationsmulighed. Det er en avanceret konfigurationsmulighed; derfor før du aktiverer xp_cmdshell , skal du aktivereVis avanceret indstilling konfigurationsmulighed. Til dette skal du udføre følgende T-SQL-kommandoer i rækkefølge.

brug mastergoexec sp_configure 'vis avanceret mulighed',1omkonfigurer med overrideExec sp_configure 'xp_cmdshell',1Genkonfigurer med tilsidesættelse

Trin 2:Brug PowerShell-script til at udfylde fillisten i T-SQL-kode

For at udføre et PowerShell-script ved hjælp af T-SQL skal du bruge xp_cmdshell procedure. Den udfører PowerShell-kommandoen, som udfylder en liste over filer og dens detaljer i Document_List tabel.
Koden er som følger:

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

Trin 3:Opret en dynamisk SQL-forespørgsel for at få filplaceringen

Opret en dynamisk SQL-forespørgsel, som itererer gennem Document_List tabel, indlæser indholdet af filen, placeret på stien angivet i Fuldt navn kolonnen, konverterer den til kolonnen VARBINAR(MAX) og indsætter den i Document_Content bord. Sammen med Fil indsætter scriptet Filnavn, Filattribut, Filstørrelse og Filtype i Document_Content bord. Scriptet bruger casen udtryk for at bestemme filtypen.

Koden er som følger:

SET @FileCount =(SELECT Count(*) FROM Document_List) WHILE ( @i <@FileCount ) BEGIN SET @FileName =(VÆLG TOP 1 navn FRA Document_List) /* Sammensæt mappeplacering og filnavn kolonne for at generere FQDN. */ SET @FileName =(SELECT TOP 1 Name FROM Document_List) SET @FileLocation =(SELECT TOP 1 fuldnavn FRA Document_List hvor navn=@FileName) SET @FileAttribute =(SELECT TOP 1 attributes FROM Document_List hvor navn=@FileName) SET @ FileCreateDate =(VÆLG TOP 1 CreationTime FRA Document_List hvor navn=@Filnavn) SET @FileSize =(VÆLG TOP 1 Længde FRA Document_List hvor navn=@Filnavn) SET @FileType =(VÆLG TOP 1 CASE HVORNÅR ( navn LIKE '%jpg%' ) ELLER ( navn LIKE '%png%' ) ELLER ( navn LIKE '%jpg%' ) ELLER ( navn LIKE '%bmp%' ) SÅ 'Billeder' NÅR (navn SOM '%txt%' )SÅ 'Tekstfiler' When ( navn SOM '%xls%' )SÅ 'Tekstfiler' Når (navn SOM '%doc%' ) SÅ 'Tekstfiler' ELLES 'Andre filer' AFSLUT SOM 'Filtype' FRA Document_List hvor navn=@Filnavn) SET @SQLText ='Indsæt i Document_Content (ID, RootDirectory, FileName, FileAttribute,FileCreateDate,FileSize,FileType,FileStreamCol) Vælg NEWID(), ''' + @FileLocation + ''', ''' + @Filnavn + ''', ''' + @FileAttribute + ''', ''' + @FileCreateDate + ''', ''' + @FileSize + ''', ' '' + @FileType + ''', bulkColumn fra Openrowset(Bulk '''+ @FileLocation + ''', Single_Blob) as tb' EXEC Sp_executesql @SQLText DELETE FROM Document_List WHERE name =@FileName SET @I =@I + 1END

Trin 4:Pak hele SQL-koden sammen i en lagret procedure

Opret en parameteriseret lagret procedure med navnet sp_Insert_Files og pak koden ind i den.

Koden for lagret procedure er som følger:

brug FileStream_DemogoCreate Procedure sp_Insert_Files@FileLoc varchar(max)as start DECLARE @FileCount INTDECLARE @I INT =0DECLARE @Filnavn NVARCHAR(max)DECLARE @SQLText NVARCHAR(max)declare @PSFiScript0)Location NCLARE(max) )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 /* Hent filnavnet fra tabellen Document_Name */ SET @FileName =(VÆLG TOP 1 navn FRA Document_List) /* Udfyld Fildetaljer fra Document_List tabel*/ SET @FileName =(VÆLG TOP 1 Navn FRA Document_List) SET @FileLocation =(VÆLG TOP 1 fuldnavn FRA Document_List hvor navn=@FileName) SET @FileAt hyldest =(VÆLG TOP 1 attributter FRA Document_List hvor navn=@Filnavn) SET @FileCreateDate =(SELECT TOP 1 CreationTime FROM Document_List where name=@FileName) SET @FileSize =(SELECT TOP 1 Length FROM Document_List where name=@FileName) / *Bestem filtype*/ SET @FileType =(VÆLG TOP 1 TILFÆLDE NÅR (navn LIKE '%jpg%') ELLER (navn LIKE '%png%') ELLER (navn LIKE '%jpg%') ELLER (navn LIKE '%bmp%' ) SÅ 'Billeder' NÅR (navn SOM '%txt%' )SÅ 'Tekstfiler' Når (navn SOM '%xls%' )SÅ 'Tekstfiler' Når (navn SOM '%doc%') SÅ 'Tekstfiler' ELSE 'Andre filer' SLUT SOM 'Filtype' FRA Document_List hvor navn=@Filnavn) SET @SQLText ='Indsæt i Document_Content (ID, RootDirectory, FileName, FileAtt ribute,FileCreateDate,FileSize,FileType,FileStreamCol) Vælg NEWID(), ''' + @FileLocation + ''', ''' + @FileName + ''', ''' + @FileAttribute + ''', '' ' + @FileCreateDate + ''', ''' + @FileSize + ''', ''' + @FileType + ''', bulkColumn fra Openrowset(Bulk '''+ @FileLocation + ''', Single_Blob) som tb' EXEC Sp_executesql @SQLText DELETE FROM Document_List WHERE name =@FileName SET @I =@I + 1ENDend

Indsæt filer ved hjælp af lagret procedure

Test nu den lagrede procedure. Jeg tilføjede et par filer til E:\Files vejviser. Indsæt filerne i SQL-tabellen ved at udføre den lagrede procedure. Koden er som følger:

brug FileStream_Demogoexec sp_Insert_Files 'E:\Files'

Lad os kontrollere, at filerne er blevet kopieret til tabellen. Til dette skal du udføre følgende kode:

vælg RootDirectory som 'Filplacering', Filnavn som 'Filnavn', FileAttribute som 'Attribut', FileCreateDate som 'Attribut', FileSize som 'Filstørrelse', FileType som 'Filtype', FileStreamCol som 'Filindhold' fra Document_Content hvor FileType='Billeder'

Outputtet af forespørgslen er som følger:

For at få adgang til filen på FILESTREAM-datalageret ved hjælp af Win32 API skal du bruge Stinavn () metode til FILESTREAM. Med Stinavn () metode, kan vi identificere den logiske sti til at detektere filen i FILESTREAM-datalageret unikt.

Koden er som følger:

vælg RootDirectory som 'Filplacering', Filnavn som 'Filnavn', FileAttribute som 'Attribut', FileCreateDate som 'Attribut', FileSize som 'Filstørrelse', FileType som 'Filtype', FileStreamCol.PathName() AS FilePathfrom Document_Content hvor FileName='RowDesign.png'

Outputtet af forespørgslen er som følger:

Lad os navigere til FILESTREAM-databeholderen (E:\Dummy-Documents) for at bekræfte, at filerne er blevet indsat. Se følgende skærmbillede:

Som du kan se, er alle filerne blevet indsat i SQL-tabeller og FileStream-beholderen.

Oversigt

I denne artikel har jeg dækket:

  1. Nyttig forespørgsel til at bekræfte forudsætningerne for FILESTREAM-funktionen.
  2. Sådan registreres en PowerShell-funktion som et modul.
  3. Forklar PowerShell-koden for at indsætte filliste i SQL-tabel ved hjælp af PowerShell-script.
  4. Forklarede koden for den lagrede procedure til at indsætte flere filer i SQL-tabel.
  5. Nyttige forespørgsler til at samle en liste over dokumenter, gemt i FILESTREAM container.

I fremtidige artikler vil jeg forklare, hvordan man sikkerhedskopierer og gendanner FILESTREAM-aktiveret database.

Hold dig opdateret!


  1. Sådan installeres MySQL Workbench på Windows

  2. Sådan gemmer du UTF8-tegn i MySQL

  3. Hvordan kan jeg tvinge entity framework til at indsætte identitetskolonner?

  4. Sådan får du den aktuelle tid i PostgreSQL