Usare BULK INSERT o OPENROWSET (BULK...) per importare dati in SQL Server

Si applica a:SQL ServerDatabase SQL di AzureIstanza gestita di SQL di Azure

In questo articolo viene fornita una panoramica sull'uso delle istruzioni BULK INSERT e INSERT...SELECT * FROM OPENROWSET(BULK...) di Transact-SQL per effettuare l'importazione in blocco di dati da un file di dati in una tabella di SQL Server o del database SQL di Azure. L'articolo include anche considerazioni sulla sicurezza per l'uso di BULK INSERT e di OPENROWSET(BULK…), nonché sull'uso di questi metodi per l'importazione bulk da un'origine dati remota.

Nota

Quando si usa BULK INSERT o OPENROWSET(BULK...), è importante comprendere in che modo la versione di SQL Server gestisce la rappresentazione. Per ulteriori informazioni, vedere la sezione "Considerazioni sulla sicurezza" di seguito in questo argomento.

Istruzione BULK INSERT

L'istruzione BULK INSERT consente di caricare dati da un file di dati a una tabella. Questa funzionalità è analoga a quella dell'opzione in del comando bcp, ma il file di dati viene letto dal processo di SQL Server. Per una descrizione della sintassi di BULK INSERT, vedere BULK INSERT (Transact-SQL).

Esempi di BULK INSERT

Funzione OPENROWSET(BULK…)

Al provider bulk per set di righe OPENROWSET si accede chiamando la funzione OPENROWSET e specificando l'opzione BULK. La funzione OPENROWSET(BULK...) consente di accedere ai dati remoti connettendosi a un'origine dei dati remota, ad esempio un file di dati, con un provider OLE DB.

Per eseguire l'importazione bulk dei dati, chiamare OPENROWSET(BULK...) da una clausola SELECT...FROM all'interno di un'istruzione INSERT. La sintassi di base per l'importazione bulk dei dati è la seguente:

INSERT ... SELECT * FROM OPENROWSET(BULK...).

Quando utilizzato in un'istruzione INSERT, OPENROWSET(BULK...) supporta gli hint di tabella. Oltre agli hint di tabella normali, ad esempio TABLOCK, la clausola BULK può accettare gli hint di tabella specializzati seguenti: IGNORE_CONSTRAINTS (ignora solo i vincoli CHECK), IGNORE_TRIGGERS, KEEPDEFAULTS e KEEPIDENTITY. Per ulteriori informazioni, vedere Hint di tabella (Transact-SQL).

Per informazioni sugli usi aggiuntivi dell'opzione BULK, vedere OPENROWSET (Transact-SQL).

Esempi di istruzioni INSERT...SELECT * FROM OPENROWSET(BULK...)

Considerazioni sulla sicurezza

Se un utente usa un account di accesso SQL Server, viene usato il profilo di sicurezza dell'account del processo di SQL Server. Un accesso eseguito tramite l'autenticazione di SQL Server non può essere autenticato all'esterno del motore di database. Pertanto, quando un comando BULK INSERT viene avviato da un account di accesso che utilizza l'autenticazione di SQL, la connessione ai dati viene effettuata utilizzando il contesto di sicurezza dell'account del processo di SQL Server (l'account utilizzato dal servizio Motore di database di SQL Server).

Per una lettura corretta dei dati di origine è necessario concedere all'account utilizzato dal motore di database di SQL Server l'accesso ai dati di origine. Di contro, se un utente di SQL Server esegue l'accesso utilizzando l'autenticazione di Windows, potrà leggere solo i file accessibili dall'account utente, indipendentemente dal profilo di sicurezza del processo di SQL Server.

Si può, ad esempio, prendere in considerazione un utente che abbia eseguito l'accesso a un'istanza di SQL Server utilizzando l'autenticazione di Windows. Perché l'utente sia in grado di utilizzare BULK INSERT o OPENROWSET per importare dati da un file di dati in una tabella di SQL Server, è necessario che l'account utente disponga dell'accesso in lettura al file di dati. Con l'accesso al file di dati, l'utente può importare i dati dal file in una tabella anche se il processo di SQL Server non dispone dell'autorizzazione per accedere al file. Non è necessario che l'utente conceda l'autorizzazione di accesso al file al processo di SQL Server.

SQL Server e Microsoft Windows possono essere configurati in modo da abilitare un'istanza di SQL Server per connettersi a un'altra istanza di SQL Server trasferendo le credenziali di un utente di Windows autenticato. Questa configurazione è nota come rappresentazione o delega. La comprensione delle modalità di gestione della sicurezza da parte della versione di SQL Server ai fini della rappresentazione dell'utente costituisce un elemento importante quando si usa BULK INSERT o OPENROWSET. La rappresentazione dell’utente fa sì che i file di dati possano trovarsi su un computer diverso rispetto al processo di SQL Server o all'utente. Se, ad esempio, un utente nel Computer_A ha accesso a un file di dati presente nel Computer_B e la delega delle credenziali è stata impostata in modo corretto, l'utente potrà connettersi a un'istanza di SQL Server in esecuzione nel Computer_C, accedere al file di dati sul Computer_B e importare in blocco i dati da quel file in una tabella sul Computer_C.

Importazione bulk in SQL Server da un file di dati remoto

Per usare BULK INSERT o INSERT...SELECT * FROM OPENROWSET(BULK...) per effettuare l'importazione in blocco dei dati da un altro computer, è necessario che il file di dati sia condiviso tra i due computer. Per specificare un file di dati condiviso, usare il relativo nome UNC (Universal Naming Convention), il cui formato generico è \\Nomeserver\Nomecondivisione\Percorso\Nomefile. Inoltre, è necessario che all'account utilizzato per l'accesso al file di dati siano state concesse le autorizzazioni richieste per la lettura del file sul disco remoto.

Ad esempio, l'istruzione BULK INSERT seguente esegue l'importazione bulk dei dati nella tabella SalesOrderDetail del database AdventureWorks da un file di dati denominato newdata.txt. Tale file di dati è memorizzato in una cartella condivisa denominata \dailyorders e presente in una directory condivisa di rete denominata salesforce in un sistema denominato computer2.

BULK INSERT AdventureWorks2022.Sales.SalesOrderDetail
   FROM '\\computer2\salesforce\dailyorders\neworders.txt';

Nota

Questa restrizione non si applica all'utilità bcp perché il client legge il file in modo indipendente da SQL Server.

Importazione bulk da Archiviazione BLOB di Azure

Quando si esegue l'importazione da Archiviazione BLOB di Azure e i dati non sono pubblici (accesso anonimo), crea credenziali con ambito database basate su una chiave di firma di accesso condiviso crittografata con una chiave master e, quindi, crea un'origine del database esterna da usare nel comando BULK INSERT.

In alternativa, crea credenziali con ambito database basate su MANAGED IDENTITY per autorizzare le richieste di accesso ai dati negli account di archiviazione non pubblici. Quando si usa MANAGED IDENTITY, Archiviazione di Azure deve concedere le autorizzazioni all'identità gestita dell'istanza aggiungendo il ruolo predefinito di Azure di controllo degli accessi in base al ruolo Collaboratore ai dati del BLOB di archiviazione che fornisce l'accesso in lettura/scrittura all'identità gestita per i contenitori Archiviazione BLOB di Azure necessari. Istanza gestita di SQL di Azure dispone di un'identità gestita assegnata dal sistema e può avere anche una o più identità gestite assegnate dall'utente. È possibile usare identità gestite assegnate dal sistema o identità gestite assegnate dall'utente per autorizzare le richieste. Per l'autorizzazione, viene usata l'identità default dell'istanza gestita, ovvero l'identità gestita assegnata dall'utente primario o l'identità gestita assegnata dal sistema se non viene specificata l'identità gestita assegnata dall'utente.

Importante

L'identità gestita è applicabile solo a SQL di Azure. SQL Server non supporta l’identità gestita.

Nota

Non usare la transazione esplicita o viene visualizzato un errore 4861.

Utilizzo di BULK INSERT

L'esempio seguente illustra come usare il comando BULK INSERT per caricare dati da un file CSV in una posizione di Archiviazione BLOB di Azure in cui è stata creata una chiave di firma di accesso condiviso. La posizione di Archiviazione BLOB di Azure è configurata come origine dati esterna. Questa operazione richiede credenziali con ambito database che usano una firma di accesso condiviso crittografata con una chiave master nel database utente.

--> Optional - a MASTER KEY is not required if a DATABASE SCOPED CREDENTIAL is not required because the blob is configured for public (anonymous) access!
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'YourStrongPassword1';
GO
--> Optional - a DATABASE SCOPED CREDENTIAL is not required because the blob is configured for public (anonymous) access!
CREATE DATABASE SCOPED CREDENTIAL MyAzureBlobStorageCredential
 WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
 SECRET = '******srt=sco&sp=rwac&se=2017-02-01T00:55:34Z&st=2016-12-29T16:55:34Z***************';

 -- NOTE: Make sure that you don't have a leading ? in SAS token, and
 -- that you have at least read permission on the object that should be loaded srt=o&sp=r, and
 -- that expiration period is valid (all dates are in UTC time)

CREATE EXTERNAL DATA SOURCE MyAzureBlobStorage
WITH ( TYPE = BLOB_STORAGE,
          LOCATION = 'https://****************.blob.core.windows.net/invoices'
          , CREDENTIAL= MyAzureBlobStorageCredential --> CREDENTIAL is not required if a blob is configured for public (anonymous) access!
);

BULK INSERT Sales.Invoices
FROM 'inv-2017-12-08.csv'
WITH (DATA_SOURCE = 'MyAzureBlobStorage');

L'esempio seguente illustra come usare il comando BULK INSERT per caricare dati da un file CSV in una posizione di Archiviazione BLOB di Azure utilizzando l’identità gestita. La posizione di Archiviazione BLOB di Azure è configurata come origine dati esterna.

--> Optional - a MASTER KEY is not required if a DATABASE SCOPED CREDENTIAL is not required because the blob is configured for public (anonymous) access!
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'YourStrongPassword1';
GO

--> Optional - a DATABASE SCOPED CREDENTIAL is not required because the blob is configured for public (anonymous) access!
CREATE DATABASE SCOPED CREDENTIAL MyAzureBlobStorageCredential 
WITH IDENTITY = 'Managed Identity';

-- NOTE: Make sure you have granted Storage Bob Data Contributor RBAC on storage to provides read/write access to the managed identity for the necessary Azure Blob Storage containers.

CREATE EXTERNAL DATA SOURCE MyAzureBlobStorage
WITH ( TYPE = BLOB_STORAGE,
          LOCATION = 'https://****************.blob.core.windows.net/invoices'
          , CREDENTIAL= MyAzureBlobStorageCredential --> CREDENTIAL is not required if a blob is configured for public (anonymous) access!
);

BULK INSERT Sales.Invoices
FROM 'inv-2017-12-08.csv'
WITH (DATA_SOURCE = 'MyAzureBlobStorage');

Importante

L'identità gestita è applicabile solo a SQL di Azure. SQL Server non supporta l’identità gestita.

Il database SQL di Azure non supporta la lettura da file di Windows.

Uso di OPENROWSET

L'esempio seguente illustra come usare il comando OPENROWSET per caricare dati da un file CSV in una posizione di Archiviazione BLOB di Azure in cui è stata creata una chiave di firma di accesso condiviso. La posizione di Archiviazione BLOB di Azure è configurata come origine dati esterna. Questa operazione richiede credenziali con ambito database che usano una firma di accesso condiviso crittografata con una chiave master nel database utente.

--> Optional - a MASTER KEY is not required if a DATABASE SCOPED CREDENTIAL is not required because the blob is configured for public (anonymous) access!
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'YourStrongPassword1';
GO
--> Optional - a DATABASE SCOPED CREDENTIAL is not required because the blob is configured for public (anonymous) access!
CREATE DATABASE SCOPED CREDENTIAL MyAzureBlobStorageCredential
 WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
 SECRET = '******srt=sco&sp=rwac&se=2017-02-01T00:55:34Z&st=2016-12-29T16:55:34Z***************';

 -- NOTE: Make sure that you don't have a leading ? in SAS token, and
 -- that you have at least read permission on the object that should be loaded srt=o&sp=r, and
 -- that expiration period is valid (all dates are in UTC time)

CREATE EXTERNAL DATA SOURCE MyAzureBlobStorage
WITH ( TYPE = BLOB_STORAGE,
          LOCATION = 'https://****************.blob.core.windows.net/invoices'
          , CREDENTIAL= MyAzureBlobStorageCredential --> CREDENTIAL is not required if a blob is configured for public (anonymous) access!
);

INSERT INTO achievements with (TABLOCK) (id, description)
SELECT * FROM OPENROWSET(
   BULK  'csv/achievements.csv',
   DATA_SOURCE = 'MyAzureBlobStorage',
   FORMAT ='CSV',
   FORMATFILE='csv/achievements-c.xml',
   FORMATFILE_DATA_SOURCE = 'MyAzureBlobStorage'
    ) AS DataFile;

Importante

Il database SQL di Azure non supporta la lettura da file di Windows.

Vedi anche