Newsgroup: it.comp.lang.delphi
Titolo: [SQL] modificare la dimensione di un campo

Ho la necessita' di modificare la lunghezza di un campo CHAR di una table;
l'ALTER TABLE dell'SQL consente solo di aggiungere o droppare campi, ma non
di modificarne il tipo. Esistono alternative, oltre a quella, ovvia e
rognosa di aggiungere un campo temporaneo della lunghezza desiderata,
riversarci dentro tutto il contenuto del campo originale con un UPDATE, poi
droppare il campo originale, ri-aggiungerlo stavolta della dimensione
corretta, updatarlo con i valori del campo temporaneo, e infine droppare il
campo temporaneo? Possibile che il meraviglioso (?) SQL non abbia una
funzione di modifica del tipo dei campi? Grazie!
Ciao, Sandro


No, l'SQL non ce l'ha. 
La modifica del tipo del campo č una operazione critica e
potenzialmente potresti incorrere in una perdita di precisione se non
in una perdita dei dati del campo.
Secondo me č giusto cosě.
Le operazioni che potrebbero compromettere il database meglio farle "a
mano"....
-=SIMO=-

Possibile che il meraviglioso SQL non abbia una funzione di modifica del tipo dei campi? 
Possibile, pero'...
Interbase - per dirne una - conserva l'informazione relativa a tipo e
lunghezza dei campi in speciali tabelle che possono essere manipolate
con comandi  SQL.
E quindi puoi non solo cambiare la lunghezza di un campo, ma anche
dare comandi molto potenti del tipo:
"per tutte le tabelle del database, cambia i campi di tipo X in campi
di tipo Y".
Inutile dire che piu' i comandi sono potenti, piu' sono pericolosi, se
usati a piffero.
Ciao
Duilio

di tipo Y".
Ok per cambiare il tipo del campo...ma il contenuto del campo chi me
lo cambia ?
ad esempio un NVARCHAR può essere trasfomato in VARCHAR ma il
contenuto non è compatibile a livello binario.
-=SIMO=-

 mano"....
secondo me piu' strumenti hai a disposizione e meglio e', a prescindere da
qualunque altra considerazione. Travasare milioni di record da un campo ad
un altro e ritravasarli nel primo e' a dir poco ridicolo, non trovi? Altri
esempi utili di conversioni automatiche potrebbero essere da INTEGER (o
FLOAT) a CHAR, che potrebbe essere fatto in automatica e senza "rischi" dal
motore del database, oppure da CHAR a BLOB, ecc. Certo alcune combinazioni
sono impossibili, o genererebbero potenziali problemi e perdite, ma altre
sarebbero perfettamente lecite e utilissime. Sob!
Ciao, Sandro

 wrote in message
news:a5g4sd$tmc$2...@newsreader.mailgate.org...

Se l'operazione di modifica dei campi viene lasciata al DBMS,
e' presumibile che esso compia un "best-fit" dei valori, in 
fase di passaggio da un tipo all'altro.  La compatibilita' 
*binaria*, quindi, non viene compromessa.
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

*binaria*, quindi, non viene compromessa.
Non credo..
NVARCHAR è UNICODE e la conversione a VARCHAR inevitabilmente comporta
una perdita di informazioni. 
In ogni caso, la sola modifica delle tabelle di sistema non equivale
alla conversione dei dati contenuti nelle tabelle ma alla sola
modifica dello schema compilato.
-=SIMO=-

 modifica dello schema compilato.
Tra l'altro il database desktop consente la modifica di tipo e dimensione
dei campi (salvo alcune combinazioni) e senza alcuna perdita di dati.
Ciao, Sandro

sarebbero perfettamente lecite e utilissime. Sob!
Vero, ma la filosofia del SQL è improntata alla sicurezza dei dati.
Credo sia per questo che nel SQL standard (ma anche in svariati
dialetti 'custom') non sia implementata una simile funzione.
Posso dirti per certo che non esiste nè in INFORMIX, nè in SQLSERVER
e (correggetemi se sbaglio..) nè in ORACLE e DB2.
Bisogna adeguarsi.. Non è poi tanto difficile farsi un tool di
conversione (usando appunto le tabelle di sistema per ottenere
informazioni sui tipi).
-=SIMO=-


E' implementato a livello BDE e non a livello RDBMS.
Nessuno ti vieta di farti un tuo tool (usando le tabelle di sistema
per ottenere informazioni sui tipi..)
-=SIMO=-

 modifica dello schema compilato.
Dipende dall'RDBMS.


 per ottenere informazioni sui tipi..)
Non si sta parlando di "tuoi tool", ma dell'uso del DBMS stesso
per modificare i dati.  Il TBatchMove, per esempio, compie un
best-fit per quei campi che hanno nomi uguali e tipi diversi ed
e' giusto che sia cosi'.



Elencami i RDBMS che si comportano nel modo da te descritto, grazie.
-=SIMO=-


Non era questo il discorso.
Si parlava del perchè SQL non supportasse (e non supporta in
effetti..) la modifica del tipo dei campi.
-=SIMO=-

 campo temporaneo?
Se la soluzione che cerchi è "server-side" ed "sql-only", puoi automatizzare
il tutto con una stored procedure, magari reperendo le informazioni sul tipo
del campo con una SELECT sulle system tables..
Se cerchi invece una soluzione "client-side", hai l'imbarazzo della
scelta...ma come hai già detto tu, c'è gia Database Desktop che lo fa.. :)
Se invece usi ADO, puoi utilizzare ADOX e farti un programmino..
-=SIMO=-

Delphi..
Rileggi il thread, io non sto parlando di alcun componente
specifico.
"Interbase - per dirne una - conserva l'informazione
relativa a tipo e lunghezza dei campi in speciali tabelle
che possono essere manipolate con comandi  SQL." 
[Duilio Foschi]
-- 
Andrea Laforgia (
walkie...@libero.it
)
"Usenet is a strange place" [Dennis Ritchie]

Sufficiente ?
Il fatto che non siano supportate da MS (ed e' poi da vedere
se siano persone "sane di mente") conferma il fatto che
dipende dal RDBMS.  La modifica di cui stiamo parlando, tra
l'altro, non puo' produrre gli "unpredictable effects" di
cui parli.



Tu questo come lo chiami ? TBatchMove.
Ripeto : in SQL **NON ESISTE** la possibilità di cambiare il tipo di un
campo con un comando singolo.
E' possibile farlo in altri modi (ad esempio con una serie di comandi SQL,
come ha giustamente detto Zortek).
In ogni caso è meglio TENERE GLI OCCHI APERTI perchè si potrebbe incorrere
in perdite dei dati.
Invece, l'ipotesi di modificare direttamente le SYSTEM TABLES è da pazzi,
per i motivi che ti ho esposto.
E' assolutamente SCONSIGLIATO modificare le system tables, perchè al RDBMS
risulterebbe uno schema compilato DIVERSO da quello effettivamente contenuto
nell'area dati a livello binario.
Le System Tables vanno usate IN LETTURA, ad esempio per reperire info sul
tipo di un campo, l'esistenza di un indice, ecc..
Non volevo offenderti. Ho sempre apprezzato i tuoi interventi in questo ng:
precisi, concisi, efficaci..
..ma credo che questa volta tu abbia letto male il post iniziale.
Della serie : "Anche i migliori sbagliano"
 :)
-=SIMO=-

..ma credo che questa volta tu abbia letto male il post iniziale.
Io credo di no.


 Io credo di no.
Non mi resta che dimostrartelo.
Leggi il prox post..
-=SIMO=-

 cui parli.
Non ne parlo io, ma chi ha sviluppato SQLServer (ovvero SYBASE..ed ora M$).
Non credo che tu sia altrettanto autorevole nel campo.
Peccheresti di saccenza...
Comunque, un esempio concreto :
Questa query eseguita contro un database INTERBASE (visto che lo conosci
cosě bene..) da come risultato, nel caso di tipo incompatibile, questo
errore :
UPDATE RDB$FIELDS
SET RDB$FIELD_TYPE=10
WHERE RDB$FIELD_NAME='RDB$6'
SELECT * FROM <TableName>
<ISC ERROR CODE: 335544334>
<ISC ERROR MESSAGE: conversion error from string '.......'>
Risultato: IMPOSSIBILE APRIRE LA TABELLA se non rimettendo a posto il tipo
del campo.
Altro caso : tipo uguale ma accorciato da CHAR(255) a CHAR(10)
UPDATE RDB$FIELDS
SET RDB$FIELD_LENGTH=10
WHERE RDB$FIELD_NAME='RDB$6'
SELECT * FROM <TableName>
<ISC ERROR CODE: 335544321>
<ISC ERROR MESSAGE: arithmetic exception, numeric overflow, or string
truncation>
Risultato: IMPOSSIBILE APRIRE LA TABELLA se non rimettendo a posto il tipo
del campo.
Altro caso : tipo uguale ma allungato da CHAR(255) a CHAR(256)
<ISC ERROR CODE: 335544321>
<ISC ERROR MESSAGE: arithmetic exception, numeric overflow, or string
truncation>
Risultato: IMPOSSIBILE APRIRE LA TABELLA se non rimettendo a posto il tipo
del campo.
Io questo lo chiamo  "unpredictable effect".....anzi "Tempo Perso"..
Convinto ??????????
Continuo a credere che la modestia sia la miglior virtů per un
programmatore.. :)
-=SIMO=-

e' giusto che sia cosi'.
Che c'entra il TBatchMove con il RDBMS ?
-=SIMO=-

Secondo me tu stai parlando di "Best-Fit" nel riversamento da un campo ad un
altro.
Purtroppo non c'entra niente con la modifica del tipo del campo.
O sbaglio ?
-=SIMO=-

di modificarne il tipo. 
almeno per l'IB, esiste anche l'istruzione
alter table NomeTabella alter column NomeColonna
p.es
.
nome tabella: tabella1
nome campo: campo1
vecchio tipo del campo: non ha importanza, perche' IB gia' lo conosce
(cmq nel mio esempio era un integer)
nuovo tipo di campo desiderato: varchar(100)
puoi scrivere:
alter table tabella1 alter column campo1 varchar(100)
e funziona regolarmente, esegue il cast, etc.
Ciao
Duilio

>Questa query eseguita contro un database INTERBASE 
questa istruzione cambia tutti i campi integer di un database in campi
varchar(20), cast  incluso
update rdb$fields
set
rdb$field_type=37,
rdb$field_length=20,
rdb$character_length=20
where rdb$field_type=8
Le system tables sono "tricky" e bisogna saperle usare.
Inoltre, a ben ricordare, c'e' anche il comando SQL :
alter table ... alter column ...
questo comando cambia il tipo di campo, e questa probabilmente era la
risposta che voleva Zortek.
Il comando esiste (a volte con la sintassi leggermente diversa alter
table ... modify column...) sicuramente in
IB, FB, Postgres, DB2, Informix, Oracle  e  SQL Server.
Ovviamente tutte le operazioni atte a cambiare il tipo di un campo
hanno senso solo quando e' possibile il cast dal formato iniziale al
formato finale.
Ciao
Duilio


Limitazioni di ALTER TABLE ..Column... (che praticamente ne limitano
l'utilizzo in gran parte dei casi., oltre ai casi di cast
incompatibile) .
Un esempio da SQLServer (ma analoghe limitazioni esistono per tutti i
db in cui esista una estensione proprietara ad ALTER TABLE per la
modifica del tipo del campo..)
"The altered column cannot be: 
- A column with a text, image, ntext, or timestamp data type.
- The ROWGUIDCOL for the table.
- A computed column or used in a computed column.
- A replicated column.
- Used in an index, unless the column is a varchar, nvarchar, or
varbinary data type, the data type is not changed, and the new size is
equal to or larger than the old size.
- Used in statistics generated by the CREATE STATISTICS statement.
-Used in a PRIMARY KEY or [FOREIGN KEY] REFERENCES constraint.
- Used in a CHECK or UNIQUE constraint, except that altering the
length of a variable-length column used in a CHECK or UNIQUE
constraint is allowed.
-Associated with a default, except that changing the length,
precision, or scale of a column is allowed if the data type is not
changed. 
Some data type changes may result in a change in the data. For
example, changing an nchar or nvarchar column to char or varchar can
result in the conversion of extended characters."
Inoltre l'ALTER COLUMN ha estensioni della sintassi proprietarie del
RDBMS in uso (fuori specifica ANSI) ovvero non-SQL ma casomai
Transact-SQL, ecc..
Ripeto: In SQL **NON ESISTE** la possibilità di modificare il tipo di
un campo.
Sempre che per SQL intendiate (STANDARD Query Language)
PS: Fare una stored procedure che risolva il problema è semplicissimo
e se ci si limita al ANSI-SQL, anche portabile se non addirittura
standard. Perchè complicarsi la vita ?
-=SIMO=-

 e funziona regolarmente, esegue il cast, etc.
ottimo :) ..dovrei decidermi a passare a IB prima o poi, se non fosse che ho
gia' un mucchio di software basato su Paradox e sulle ttable.. :(
Ciao, Sandro

 Ciao, Sandro
Ciao, Antò.

 where RDB$FIELD_NAME = 'RDB$nn'
con il sistema precedente puoi aumentare o dimunire la dimensione del campo 
mentre con quello successivo solo aumentare:
alter table tuatabella
alter column tucolonna type varchar(n)
dove n deve essere superiore alla vecchia dimensione.
Aricia, Antò.

 Ciao, Sandro
Con MySql la sintassi per passare da un campo varchar (30) a varchar (50) se
ricordo bene dovrebbe essere
ALTER TABLE NomeTabella CHANGE NomeCampo NomeCampo VARCHAR (50)
Saluti NEA

 ALTER TABLE NomeTabella CHANGE NomeCampo NomeCampo VARCHAR (50)
Grazie per la dritta Nea (e grazie a tutti per l'entusiasmo, vedo che l'SQL
accende gli animi :) ).. resta il fatto che l'SQL standard (e il Local SQL
di BDE) non prevede il cambio del tipo di campo, ne' il "rename" di un campo
(altra cosa talvolta utile nella gestione delle tabelle), e bisogna
affidarsi ai dialetti del linguaggio, la cui sintassi cambia a seconda del
motore database usato.
Ciao, Sandro