Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bulk Insert particolare

42 views
Skip to first unread message

Luigi

unread,
Sep 12, 2005, 8:25:01 AM9/12/05
to
Ciao a tutti,
vorrei realizzare una Bulk Insert che mi copi il contenuto di un file di
testo csv in una tabella. La difficoltà che sto incontrando è che questa
tabella ha 3 campi che non dovrebbero essere interessati da questa copia.
La struttura della tabella è:

Session (int)
Flusso_alimentante (varchar)
numero_riga (int)
Campo1
Campo2
Campo3
.........
Campo10

Il file (o meglio, I file, dato che sono più di uno) ha 10 campi, e questi
campi andranno copiati nei campi 1, 2,...10.
Nel campo Session ci va un default (pari a 0 quando si esegue il
caricamento), nel campo Flusso_alimentante il nome del file csv che sto
caricando, e nel campo numero_riga un numero (incrementale) legato ai record
presenti in ciascun file (primo record, secondo record, e così via).
Non riesco però a trovare una soluzione per implementare il tutto.
Qualcuno ha un'idea?
Grazie

Lorenzo Benaglia

unread,
Sep 12, 2005, 8:50:16 AM9/12/05
to
Luigi wrote:
> Nel campo Session ci va un default (pari a 0 quando si esegue il
> caricamento), nel campo Flusso_alimentante il nome del file csv che
> sto caricando, e nel campo numero_riga un numero (incrementale)
> legato ai record presenti in ciascun file (primo record, secondo
> record, e così via).
> Non riesco però a trovare una soluzione per implementare il tutto.

Ciao Luigi,

non puoi effettuare questa operazione in una "botta" sola.
- Creati una tabella di appoggio avente la stessa struttura del file da
importare.
- Con una BULK INSERT popola questa tabella;
- Popola la tabella di destinazione tramite il comando INSERT...SELECT
valorizzando opportunamente le colonne mancanti: per la colonna Session
definisci un DEFAULT sulla tabella di destinazione ed escludila dalla SELECT
LIST, per Flusso_alimentante "schianta" il suo valore in una costante oppure
se hai intenzione di inglobare il tutto in una stored procedure, prevedi una
variabile di input che valorizzerai opportunamente ad ogni importazione con
il nome del file, infine per numero_riga... non ho capito come lo vuoi
valorizzare :-)
"numero (incrementale)legato ai record presenti in ciascun file (primo


record, secondo record, e così via)"

Che significa questa frase?

Ciao!

--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

Luigi

unread,
Sep 12, 2005, 9:04:03 AM9/12/05
to
Ciao Lorenzo, grazie per la risposta.
In effetti avevo immaginato che non potevo fare tutto in una botta sola.
Come numero_riga, che sarebbe un valore incrementale, vorrei (dovrei)
metterci il numero della riga del file che in quel momento sto caricando.
Ti faccio un esempio.
Ho il file Flusso1.txt che contiene ad esempio 50 righe (con tutti i 10
campi che andranno importati).
Nella tabella che conterrà i dati, dovranno esserci 50 righe con

flusso_alimentante = Flusso1.txt

e

numero_riga che avrà i valori da 1 a 50, in base appunto al numero delle
righe che sono presenti nel file alimentante.
Tu come penseresti di fare?

"Lorenzo Benaglia" ha scritto:

Luigi

unread,
Sep 12, 2005, 9:39:10 AM9/12/05
to
Uno abbozzo di soluzione potrebbe essere questo.
Mi creo una stored procedure per ognuno dei file, di questo tipo:

CREATE PROCEDURE up_CaricaFile1
AS

BULK INSERT mioDB..IT_SYSTEM_LOAD_TEMP FROM 'c:\File1.txt'
WITH
(
FIELDTERMINATOR = ';',
ROWTERMINATOR = '|\n',
DATAFILETYPE = 'char'
)

declare @Campo1 varchar(100)
declare @Campo2 varchar(100)
declare @Campo3 varchar(100)
declare @Campo4 varchar(100)
declare @Campo5 varchar(100)
declare @Campo6 varchar(100)
declare @Campo7 varchar(100)
declare @Campo8 varchar(100)
declare @Campo9 varchar(100)
declare @Campo10 varchar(100)

select @Campo1 = Campo1 FROM IT_SYSTEM_LOAD_TEMP
/*
eccetera per tutti gli altri 9 campi
*/

-- Inserisco nella tabella finale
INSERT IT_SYSTEM_LOAD values (
0,
'File1.txt1',
'------',
@Campo1,
@Campo2,
@Campo3,
@Campo4,
@Campo5,
@Campo6,
@Campo7,
@Campo8,
@Campo9,
@Campo10)

Il problema è che non ho trovato un modo per valore il campo che ho segnato
come '------' e che dovrebbe contenere il valore incrementale della riga (da
1 fino al numero di righe che contiene il file txt).


Lorenzo Benaglia

unread,
Sep 12, 2005, 10:12:43 AM9/12/05
to
Luigi wrote:
> numero_riga che avrà i valori da 1 a 50, in base appunto al numero
> delle righe che sono presenti nel file alimentante.
> Tu come penseresti di fare?

Nella tabella di appoggio definirei una colonna IDENTITY che si
autoincrementa in modo automatico.
Il fatto è che se la tabella contiene un numero differente di colonne
rispetto al file sorgente, sarai costretto a ricorrere ad un file di formato
dove andrai ad indicare la corrispondenza tra le colonne del file di input
con quelle della tabella di destinazione.

Dato che il discorso si complica un attimino ti propongo un esempio
completo.
Supponiamo di voler importare il seguente file C:\Students.csv:

<BOF>
Lorenzo;Benaglia
Luca;Bianchi
Andrea;Montanari
Gianluca;Hotz

<EOF>

Come prima cosa vado a definire il file di formato C:\Students.fmt:

<BOF>
8.0
3
1 SQLCHAR 0 0 "" 0 numero_riga ""
2 SQLCHAR 0 10 ";" 2 FirstName SQL_Latin1_General_CP1_CI_AS
3 SQLCHAR 0 10 "\r\n" 3 LastName SQL_Latin1_General_CP1_CI_AS

<EOF>

Ora da Query Analyzer esegui il seguente script:

USE tempdb
GO

/* Definisco la tabella dbo.Students */
CREATE TABLE dbo.Students(
Session int NOT NULL DEFAULT 0,
Flusso_alimentante varchar(15),
numero_riga int NOT NULL,
FirstName varchar(10) NOT NULL,
LastName varchar(10) NOT NULL
)
GO

/* Definisco la stored procedure dbo.up_ImportStudents */
CREATE PROCEDURE dbo.up_ImportStudents(
@FileName varchar(15)
)
AS
SET NOCOUNT ON

/* Definisco la tabella di appoggio */
CREATE TABLE #TempTable(
numero_riga int NOT NULL IDENTITY,
FirstName varchar(10) NOT NULL,
LastName varchar(10) NOT NULL
)

/* La popolo con la BULK INSERT */
EXEC (
'BULK INSERT #TempTable ' +
'FROM ''' + @FileName + ''' ' +
'WITH(FORMATFILE = ''C:\Students.fmt'')'
)
SET NOCOUNT OFF

/* Popolo la tabella dbo.Students */
INSERT dbo.Students(
Flusso_alimentante
, numero_riga
, FirstName
, LastName
)
SELECT
@FileName
, numero_riga
, FirstName
, LastName
FROM #TempTable
GO

/* La eseguo */
EXEC dbo.up_ImportStudents 'C:\Students.csv'

/* Vediamo */
SELECT *
FROM dbo.Students
GO

/* Output:

Session Flusso_alimentante numero_riga FirstName LastName
----------- ------------------ ----------- ---------- ----------
0 C:\Students.csv 1 Lorenzo Benaglia
0 C:\Students.csv 2 Luca Bianchi
0 C:\Students.csv 3 Andrea Montanari
0 C:\Students.csv 4 Gianluca Hotz

(4 row(s) affected)

*/

/* Pulizia */
DROP PROCEDURE dbo.up_ImportStudents
DROP TABLE dbo.Students


Approfondisci il discorso leggendo i seguenti paragrafi dei Books Online:

"Using Format Files"
http://msdn.microsoft.com/library/en-us/adminsql/ad_impt_bcp_9yat.asp

"Using a Data File with Fewer Fields"
http://msdn.microsoft.com/library/en-us/adminsql/ad_impt_bcp_57qd.asp

Luigi

unread,
Sep 12, 2005, 10:46:01 AM9/12/05
to
Grazie immenso per l'esempio dettagliato Lorenzo.
Un dubbio: il file di formato devo definirlo lo stesso anche se il file csv
di alimentazione ha cmq lo stesso numero di campi della tabella da riempire?
I miei file, infatti, potranno contenere valori NULL, ma sono cmq presenti
tutti.
Ad esempio:

valore1;valore2;;;valore5;valore6;;;;valore10

Ho quindi tutti e 10 i campi, anche se ne sono valorizzati solo 5.

"Lorenzo Benaglia" ha scritto:

Lorenzo Benaglia

unread,
Sep 12, 2005, 11:05:02 AM9/12/05
to
Luigi wrote:
> Un dubbio: il file di formato devo definirlo lo stesso anche se il
> file csv di alimentazione ha cmq lo stesso numero di campi della
> tabella da riempire?

No, ma se segui il mio esempio la tabella di appoggio avrà la colonna
identity numero_riga che tu non hai nei file csv che vuoi importare...

Luigi

unread,
Sep 12, 2005, 11:20:03 AM9/12/05
to
Quindi se non utilizzassi il file di formato, non potrei popolarmi la colonna
Identity della tabella temporanea?
Se utilizzo la Bulk Insert che mi inserisce tutti i campi tranne il primo,
che è di tipo Identity, non funzionerebbe?


"Lorenzo Benaglia" ha scritto:

Lorenzo Benaglia

unread,
Sep 12, 2005, 11:31:42 AM9/12/05
to
Luigi wrote:
> Quindi se non utilizzassi il file di formato, non potrei popolarmi la
> colonna Identity della tabella temporanea?

Esatto. La BULK INSERT darebbe errore. Fai prima a provare che a chiedere...

> Se utilizzo la Bulk Insert che mi inserisce tutti i campi tranne il
> primo, che è di tipo Identity, non funzionerebbe?

Oh mamma, se usi un file di formato funziona, altrimenti se il numero di
colonne del file da importare differisce da quello della tabella di
destinazione otterrai un errore.

E' tutto spiegato nei paragrafi dei BOL che ti ho segnalato!!

Luigi

unread,
Sep 12, 2005, 2:47:03 PM9/12/05
to
Ok Lorenzo, direi che è più sufficiente. Grazie davvero per la tua
disponibilità e pazienza.


"Lorenzo Benaglia" ha scritto:

Luigi

unread,
Sep 14, 2005, 4:54:02 AM9/14/05
to
Ciao Lorenzo,
ho fatto un file di formato di questo tipo:

<BOF>
8.0
34
1 SQLCHAR 0 0 "" 0 row_number ""
2 SQLCHAR 0 100 ";" 2 system_name SQL_Latin1_General_CP1_CI_AS
3 SQLCHAR 0 100 ";"
3 system_short-description SQL_Latin1_General_CP1_CI_AS
4 SQLCHAR 0 100 ";" 4 application SQL_Latin1_General_CP1_CI_AS
5 SQLCHAR 0 100 ";" 5 server_name SQL_Latin1_General_CP1_CI_AS
6 SQLCHAR 0 100 ";" 6 operating_system SQL_Latin1_General_CP1_CI_AS
7 SQLCHAR 0 100 ";" 7 server_hw SQL_Latin1_General_CP1_CI_AS
8 SQLCHAR 0 100 ";" 8 location SQL_Latin1_General_CP1_CI_AS
9 SQLCHAR 0 100 ";" 9 engine_middleware SQL_Latin1_General_CP1_CI_AS
10 SQLCHAR 0 100 ";" 10 database SQL_Latin1_General_CP1_CI_AS
11 SQLCHAR 0 100 ";" 11 business_owner SQL_Latin1_General_CP1_CI_AS
12 SQLCHAR 0 100 ";" 12 technical_owner SQL_Latin1_General_CP1_CI_AS
13 SQLCHAR 0 100 ";" 13 opco SQL_Latin1_General_CP1_CI_AS
14 SQLCHAR 0 100 ";"
14 sox_business_processes_flag SQL_Latin1_General_CP1_CI_AS
15 SQLCHAR 0 100 ";" 15 sox_relevant SQL_Latin1_General_CP1_CI_AS
16 SQLCHAR 0 100 ";" 16 sox_relevant_reason SQL_Latin1_General_CP1_CI_AS
17 SQLCHAR 0 100 ";" 17 type SQL_Latin1_General_CP1_CI_AS
18 SQLCHAR 0 100 ";" 18 gita_domain_code SQL_Latin1_General_CP1_CI_AS
19 SQLCHAR 0 100 ";" 19 gita_subdomain-code SQL_Latin1_General_CP1_CI_AS
20 SQLCHAR 0 100 ";"
20 gita_domain_description SQL_Latin1_General_CP1_CI_AS
21 SQLCHAR 0 100 ";"
21 gita_subdomain_description SQL_Latin1_General_CP1_CI_AS
22 SQLCHAR 0 100 ";" 22 component SQL_Latin1_General_CP1_CI_AS
23 SQLCHAR 0 100 ";"
23 sox_relevant_flag_for_component SQL_Latin1_General_CP1_CI_AS
24 SQLCHAR 0 100 ";" 24 outsourced_flag SQL_Latin1_General_CP1_CI_AS
25 SQLCHAR 0 100 ";" 25 outsourcing_company SQL_Latin1_General_CP1_CI_AS
26 SQLCHAR 0 100 ";"
26 business_process_description SQL_Latin1_General_CP1_CI_AS
27 SQLCHAR 0 100 ";" 27 privacy_information SQL_Latin1_General_CP1_CI_AS
28 SQLCHAR 0 100 ";"
28 confidentiality_information SQL_Latin1_General_CP1_CI_AS
29 SQLCHAR 0 100 ";" 29 rto_target SQL_Latin1_General_CP1_CI_AS
30 SQLCHAR 0 100 ";" 30 rto_actual SQL_Latin1_General_CP1_CI_AS
31 SQLCHAR 0 100 ";" 31 rpo_target SQL_Latin1_General_CP1_CI_AS
32 SQLCHAR 0 100 ";" 32 rpo_actual SQL_Latin1_General_CP1_CI_AS
33 SQLCHAR 0 100 ";" 33 sla_category SQL_Latin1_General_CP1_CI_AS
34
SQLCHAR 0 100 "\r\n" 34 privacy_data_responsible SQL_Latin1_General_CP1_CI_AS
<EOF>


Non ho capito però dai BOL se posso mettere 0 (zero) come "Lunghezza del
prefisso". Nel tuo esempio hai messo 0 a tutti i campi, ma dice che se un
campo può essere NULL (ed è il mio caso), ci vorrebbe un altro valore.
Tu cosa ne dici?
Grazie

Lorenzo Benaglia

unread,
Sep 14, 2005, 5:33:17 AM9/14/05
to
Luigi wrote:
> Non ho capito però dai BOL se posso mettere 0 (zero) come "Lunghezza
> del prefisso". Nel tuo esempio hai messo 0 a tutti i campi, ma dice
> che se un campo può essere NULL (ed è il mio caso), ci vorrebbe un
> altro valore.
> Tu cosa ne dici?

Ciao Luigi,

il prefisso è richiesto solo in fase di esportazione quando le colonne di
una tabella accettano il valore NULL.
I Books Online nel paragrafo "Prefix Length"
http://msdn.microsoft.com/library/en-us/adminsql/ad_impt_bcp_797s.asp
riportano:

"Null values are represented as an empty field when copied from an instance
of SQL Server to a data file. To indicate that the field is empty
(represents NULL), the field prefix contains the value -1. Any SQL Server
column that allows null values requires a prefix length of 1 or greater,
depending on the file storage type.

Use these prefix lengths when bulk copying data from an instance of SQL
Server to a data file, storing the data using either native data types or as
ASCII characters (text file)".

Ti allego un nuovo esempio dove rispetto al precedente ho eliminato il nome
di 2 studenti e ho definito la colonna FirstName in modo che accetti il
valore NULL:

C:\Students.csv:
---------------

<BOF>
Lorenzo;Benaglia
;Bianchi
Andrea;Montanari
;Hotz

<EOF>


C:\Students.fmt:
---------------

<BOF>
8.0
3
1 SQLCHAR 0 0 "" 0 numero_riga ""
2 SQLCHAR 0 10 ";" 2 FirstName SQL_Latin1_General_CP1_CI_AS
3 SQLCHAR 0 10 "\r\n" 3 LastName SQL_Latin1_General_CP1_CI_AS

<EOF>


USE tempdb
GO

/* Definisco la tabella dbo.Students */
CREATE TABLE dbo.Students(
Session int NOT NULL DEFAULT 0,
Flusso_alimentante varchar(15),
numero_riga int NOT NULL,

FirstName varchar(10) NULL,


LastName varchar(10) NOT NULL
)
GO

/* Definisco la stored procedure dbo.up_ImportStudents */
CREATE PROCEDURE dbo.up_ImportStudents(
@FileName varchar(15)
)
AS
SET NOCOUNT ON

/* Definisco la tabella di appoggio */
CREATE TABLE #TempTable(
numero_riga int NOT NULL IDENTITY,

FirstName varchar(10) NULL,

/* Output:

0 C:\Students.csv 2 NULL Bianchi


0 C:\Students.csv 3 Andrea Montanari

0 C:\Students.csv 4 NULL Hotz

(4 row(s) affected)

*/

/* Pulizia */
DROP PROCEDURE dbo.up_ImportStudents
DROP TABLE dbo.Students


Come vedi il file di formato è sempre quello e SQL Server ha interpretato
correttamente la mancanza del nome nel file di origine come valore NULL
nella tabella di destinazione.

> Grazie
Prego.

Ciao!

Luigi

unread,
Sep 14, 2005, 5:50:03 AM9/14/05
to
Grazie Lorenzo.
Praticamente ho lasciato inalterato il file di formato e ho messo NULL a
tutte le colonne della tabella temporanea (tranne la row_number di tipo
Identity ovviamente), in modo che accettino valori nulli.
Ti riporto tutta la stored procedure come l'ho fatta (sperando che si possa
capire un qualcosa).

CREATE PROCEDURE dbo.up_ImportITSystem (
@FileName varchar(30)
)
AS

SET NOCOUNT ON

/* Definisco la tabella di appoggio */

CREATE TABLE #TempItSystemLoad
(
[row_number] [int] IDENTITY (1, 1) NOT NULL,
[system_name] [varchar] (100) NULL,
[system_short_description] [varchar] (100) NULL,
[application] [varchar] (100) NULL,
[server_name] [varchar] (100) NULL,
[operating_system] [varchar] (100) NULL,
[server_hw] [varchar] (100) NULL,
[location] [varchar] (100) NULL,
[engine_middleware] [varchar] (100) NULL ,
[database] [varchar] (100) NULL,
[business_owner] [varchar] (100) NULL ,
[technical_owner] [varchar] (100) NULL,
[opco] [varchar] (100) NULL,
[sox_business_processes_flag] [varchar] (100) NULL,
[sox_relevant] [varchar] (100) NULL,
[sox_relevant_reason] [varchar] (100) NULL,
[type] [varchar] (100) NULL,
[gita_domain_code] [varchar] (100) NULL,
[gita_subdomain_code] [varchar] (100) NULL,
[gita_domain_description] [varchar] (100) NULL,
[gita_subdomain_description] [varchar] (100) NULL,
[component] [varchar] (100) NULL,
[sox_relevant_flag_for_component] [varchar] (100) NULL,
[outsourced_flag] [varchar] (100) NULL,
[outsourcing_company] [varchar] (100) NULL,
[business_process_code] [varchar] (100) NULL,
[business_process_description] [varchar] (100) NULL,
[privacy_information] [varchar] (100) NULL,
[confidentiality_information] [varchar] (100) NULL,
[rto_target] [varchar] (100) NULL,
[rto_actual] [varchar] (100) NULL,
[rpo_target] [varchar] (100) NULL,
[rpo_actual] [varchar] (100) NULL,
[sla_category] [varchar] (100) NULL,
[privacy_data_responsible] [varchar] (100) NULL
)

/* La popolo con la BULK INSERT */
EXEC (

'BULK INSERT #TempITSystemLoad' +


'FROM ''' + @FileName + ''' ' +

'WITH(FORMATFILE = ''C:\it_system_load.fmt'')'
)

SET NOCOUNT OFF

/* Popolo la tabella sarbox.IT_SYSTEM_LOAD */

INSERT IT_SYSTEM_LOAD(
feeding_flow,
row_number,
system_name,
system_short_description,
application,
server_name,
operating_system ,
server_hw,
location,
engine_middleware,
[database],
business_owner,
technical_owner,
opco,
sox_business_processes_flag ,
sox_relevant,
sox_relevant_reason,
type,
gita_domain_code,
gita_subdomain_code,
gita_domain_description,
gita_subdomain_description,
component,
sox_relevant_flag_for_component,
outsourced_flag,
outsourcing_company,
business_process_code,
business_process_description,
privacy_information,
confidentiality_information,
rto_target,
rto_actual,
rpo_target,
rpo_actual,
sla_category,
privacy_data_responsible
)
SELECT
@FileName,
row_number,
system_name,
system_short_description,
application,
server_name,
operating_system ,
server_hw,
location,
engine_middleware,
[database],
business_owner,
technical_owner,
opco,
sox_business_processes_flag,
sox_relevant,
sox_relevant_reason,
type,
gita_domain_code,
gita_subdomain_code,
gita_domain_description,
gita_subdomain_description,
component,
sox_relevant_flag_for_component,
outsourced_flag,
outsourcing_company,
business_process_code,
business_process_description,
privacy_information,
confidentiality_information,
rto_target,
rto_actual,
rpo_target,
rpo_actual,
sla_category,
privacy_data_responsible

FROM #TempItSystemLoad

GO

Luigi

unread,
Sep 14, 2005, 6:41:05 AM9/14/05
to
Non capisco perchè facendo:

EXEC dbo.up_Import_ITSystem 'C:\FileA.csv'

mi da' il seguente errore:

Server: messaggio 170, livello 15, stato 1, riga 1
Riga 1: sintassi non corretta in prossimità di 'C:\FileA.csv'.

(righe interessate: 0)

malgrado il proprietario sia corretto, e i file siano nelle giuste posizioni


"Lorenzo Benaglia" ha scritto:

Luigi

unread,
Sep 14, 2005, 6:59:02 AM9/14/05
to
Provando a lanciare solo la Bulk Insert da sola:

BULK INSERT TempItSystemLoad FROM 'c:\FileA.csv'
WITH (FORMATFILE = 'c:\it_system_load.fmt')

mi da' il seguente errore:

Server: messaggio 4820, livello 16, stato 1, riga 1
Impossibile eseguire l'inserimento di massa. La versione del file di formato
'c:\it_system_load.fmt' è sconosciuta


Non capisco come mai.
Il file di formato è:


<BOF>
8.0
35

26 SQLCHAR 0 100 ";" 26 business_process_code SQL_Latin1_General_CP1_CI_AS
27 SQLCHAR 0 100 ";"
27 business_process_description SQL_Latin1_General_CP1_CI_AS
28 SQLCHAR 0 100 ";" 28 privacy_information SQL_Latin1_General_CP1_CI_AS
29 SQLCHAR 0 100 ";"
29 confidentiality_information SQL_Latin1_General_CP1_CI_AS
30 SQLCHAR 0 100 ";" 30 rto_target SQL_Latin1_General_CP1_CI_AS
31 SQLCHAR 0 100 ";" 31 rto_actual SQL_Latin1_General_CP1_CI_AS
32 SQLCHAR 0 100 ";" 32 rpo_target SQL_Latin1_General_CP1_CI_AS
33 SQLCHAR 0 100 ";" 33 rpo_actual SQL_Latin1_General_CP1_CI_AS
34 SQLCHAR 0 100 ";" 34 sla_category SQL_Latin1_General_CP1_CI_AS
35
SQLCHAR 0 100 "\r\n" 35 privacy_data_responsible SQL_Latin1_General_CP1_CI_AS
<EOF>

Mi rimane un mistero come mai dice che la versione è sconosciuta.

Lorenzo Benaglia

unread,
Sep 14, 2005, 8:14:11 AM9/14/05
to
Luigi wrote:
> Provando a lanciare solo la Bulk Insert da sola:
>
> BULK INSERT TempItSystemLoad FROM 'c:\FileA.csv'
> WITH (FORMATFILE = 'c:\it_system_load.fmt')
>
> mi da' il seguente errore:
>
> Server: messaggio 4820, livello 16, stato 1, riga 1
> Impossibile eseguire l'inserimento di massa. La versione del file di
> formato 'c:\it_system_load.fmt' è sconosciuta

Il paragrafo "Using Format Files"
http://msdn.microsoft.com/library/en-us/adminsql/ad_impt_bcp_9yat.asp che ti
ho segnalato in precedenza riporta:

"The format file is a tab-delimited text file with a specific structure."

Il tuo format file rispecchia quella struttura?

Lorenzo Benaglia

unread,
Sep 14, 2005, 8:33:58 AM9/14/05
to
Luigi wrote:
> Penso che la rispecchi. Ho creato un file di testo (salvato poi come
> fmt) in cui i valori che ho riportato sono divisi da tabulazioni.

Beh, SQL Server ha sempre ragione :-)
Ricontrolla con più calma e troverai l'errore.

Lorenzo Benaglia

unread,
Sep 16, 2005, 11:26:45 AM9/16/05
to
Luigi wrote:
> quindi con, ad esempio 50 record con Session = 0
> riportarli in blocco in una tabella uguale, solo che la Session
> dovrebbe avere un valore incrementale che aumenta man mano in base a
> queste importazioni in blocco (ad es. 50 record con Session=1, 45
> record con Session=2, ecc. ecc.).

> Tu come penseresti di fare?

Come prima cosa dovrei capire cosa vuoi fare.
Facciamo così, se mi prepari un esempietto bello chiaro come quelli che ti
ho fornito io vedrò di darti una mano, OK?

> Grazie
Prego.

Ciao!

Luigi

unread,
Sep 19, 2005, 3:46:01 AM9/19/05
to
Ciao Lorenzo,
ti faccio allora un esempio, spero il più chiaro possibile della situazione.
Come sai è stata fatta un'importazione di dati tramite una Bulk Insert da
dei file csv.
Ho riempito quindi una tabella la cui struttura è simile a questa (ho solo
tolto un po' di campi di soli attributi, il che non cambia la sostanza).

CREATE TABLE [dbo].[NETWORK_ELEMENT_LOAD] (
[session] [int] NOT NULL ,
[feeding_flow] [varchar] (100) NOT NULL ,
[row_number] [int] NOT NULL ,
[network_element_name] [varchar] (100) NULL ,
[type] [varchar] (100) NULL
) ON [PRIMARY]
GO

Come forse ti ricordi, nel campo feeding_flow c'è il nome del file che
alimenta, nel campo session c'è il valore 0 (zero), e row_number è un
incrementale.
Una volta caricata questa tabella (metti ad esempio con 5 record):

[Tabella di alimentazione]
[session] - [feeding_flow] - [row_number] - [network_element_name] - [type]
0 c:\F6.csv 1 network_element_name1 type1
0 c:\F6.csv 2 network_element_name2 type2
0 c:\F6.csv 3 network_element_name3 type3
0 c:\F6.csv 4 network_element_name4 type4
0 c:\F6.csv 5 network_element_name5 type5

Da questa tabella devo caricarne una di "storico", che deve mantenere gli
stessi dati, tranne che la Session deve valere 1,2,3,4.....aumentando di uno
ogni volta che riporto questi 5 record nella tabella di storico.
Quindi, con la Bulk Insert ho caricato i 5 reccord soprariportati, li devo
mettere ora nella tabella di storico in modo che appaiano così fatti.

[Tabella di storico]
[session] - [feeding_flow] - [row_number] - [network_element_name] - [type]
1 c:\F6.csv 1 network_element_name1 type1
1 c:\F6.csv 2 network_element_name2 type2
1 c:\F6.csv 3 network_element_name3 type3
1 c:\F6.csv 4 network_element_name4 type4
1 c:\F6.csv 5 network_element_name5 type5

Come vedi l'unica diversità è il campo Session, ora vale 1.
Svuoto quindi la tabella di caricamento, la ripopolo con un altro successivo
file alimentante (e avrà sempre Session = 0 nella tabella alimentata), e
riporto tutto nello storico, questa volta con session però pari a 2:

[Tabella di storico]
[session] - [feeding_flow] - [row_number] - [network_element_name] - [type]
2 c:\F6.csv 1 network_element_name11 type11
2 c:\F6.csv 2 network_element_name21 type21
2 c:\F6.csv 3 network_element_name31 type31
2 c:\F6.csv 4 network_element_name41 type41
2 c:\F6.csv 5 network_element_name51 type51

Come vedi il problema è che non è possibile settare il campo Session con un
incrementale normale, perchè questo incrementale dovrebbe funzionare, come
dire, a gruppi di record, invece che con uno solo.
Tu come faresti una cosa del genere? (sperando che io sia stato abbastanza
chiaro nello spiegarti il tutto).
Ti ringrazio

Lorenzo Benaglia

unread,
Sep 19, 2005, 4:04:49 AM9/19/05
to
Luigi wrote:
> Da questa tabella devo caricarne una di "storico", che deve mantenere
> gli stessi dati, tranne che la Session deve valere
> 1,2,3,4.....aumentando di uno ogni volta che riporto questi 5 record
> nella tabella di storico.

Prima di popolare la tabella di storico ti calcoli il massimo valore di
Session utilizzando la funzione di aggregazione MAX(), lo incrementi di 1 e
lo assegni ad una variabile locale. Questa variabile la utilizzerai nella
INSERT finale per popolare la tabella di storico con i dati della tabella di
appoggio.

0 new messages