Hibernate tiene una mala costumbre: si uno lo deja, hace la base de datos como se le ocurre. Qué quiero decir con esto? que si 2 veces le decimos que lo haga, e intentamos comparar los esquemas resultantes, serán distintos, porque no mantiene el órden de las columnas dentro de las tablas.
Si el programa va a buscar los datos haciendo selects por nombre de columna, no habrá problemas (e hibernate los hace así) pero al querer comparar 2 esquemas de desarrollo, para detectar las diferencias y poder aplicar los cambios, nos encontraremos que tablas que no tienen diferencias aparecen como diferentes.
Con este panorama (y muchas, muchas tablas que comparar a mano) es que me armé un script en php que compara tablas y columnas entre 2 esquemas, para listar los cambios necesarios para llevar la base original a la base de ejemplo.
Atención: NO CHEQUEA FK ni CONSTRAINTS ni INDICES es sólo para tablas.
<?
function db_open($database){
$serverName = "YourServerHere";
$connectionInfo = array( "Database"=>$database);
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if( !$conn ) {
echo "Connection could not be established.\n";
die( print_r( sqlsrv_errors(), true));
}
return $conn;
}
function GetArrayTablas($conn){
$sql="SELECT so.name AS Tabla, sc.name AS Columna, st.name AS Tipo, sc.max_length AS Tamanio,
CASE sc.is_nullable
when 0 then 'NOT NULL'
else 'NULL'
END AS Nullificable
FROM sys.objects so INNER JOIN sys.columns sc ON so.object_id = sc.object_id
INNER JOIN sys.types st ON st.system_type_id = sc.system_type_id AND st.name != 'sysname'
WHERE so.type = 'U' ORDER BY so.name, sc.name";
$res=sqlsrv_query($conn,$sql);
while($row=sqlsrv_fetch_array($res,SQLSRV_FETCH_ASSOC)){
$miarray['Tipo']=strtolower($row['Tipo']) ;
$miarray['Tamanio']=strtolower($row['Tamanio']) ;
$miarray['Null']=strtolower($row['Nullificable']) ;
if(trim($miarray['Tipo'])=='nvarchar'){
if($miarray['Tamanio']==510){
$miarray['Tamanio']=255;
} else {
$miarray['Tamanio']=($miarray['Tamanio']/2);
}
}
$origen[strtolower($row['Tabla'])][strtolower($row['Columna'])]=$miarray;
}
return $origen;
}
$conn=db_open("DbEjemplo");
$origen=GetArrayTablas($conn);
$conn=db_open("DbDestino");
$destino=GetArrayTablas($conn);
//recorro origen, a ver si a destino le falta algo (o hay que modificar algo)
$tablas=(array_keys($origen));
for ($i=0;$i<count($tablas);$i++){
//me fijo que exista en destino:
if(!array_key_exists($tablas[$i],$destino)){
echo "tabla ".$tablas[$i]." no existe en destino==> debo crear!\n";
} else {
//si existe, asique habra que verificar las columnas!
$columnas=(array_keys($origen[$tablas[$i]]));
for($j=0;$j<count($columnas);$j++){
//me fijo que exista!
if(array_key_exists($columnas[$j],$destino[$tablas[$i]])){
//la columna existe!
//chequeo valores (tipo, tamanio, null)
$cambio=0;
//chequeo tipo!
if($origen[$tablas[$i]][$columnas[$j]]['Tipo']!=$destino[$tablas[$i]][$columnas[$j]]['Tipo']){
//echo "CAMBIO EL TIPO!\n";
$cambio=1;
}
if($origen[$tablas[$i]][$columnas[$j]]['Tamanio']!=$destino[$tablas[$i]][$columnas[$j]]['Tamanio']){
//echo "CAMBIO EL Tamanio!\n";
if($origen[$tablas[$i]][$columnas[$j]]['Tamanio']=='-1'){
$origen[$tablas[$i]][$columnas[$j]]['Tamanio']='max';
}
$cambio=1;
}
if($origen[$tablas[$i]][$columnas[$j]]['Null']!=$destino[$tablas[$i]][$columnas[$j]]['Null']){
//echo "CAMBIO EL Null!\n";
$cambio=1;
}
if($cambio==1){
if(trim($origen[$tablas[$i]][$columnas[$j]]['Tipo'])=='int' ||
trim($origen[$tablas[$i]][$columnas[$j]]['Tipo'])=='ntext' ||
trim($origen[$tablas[$i]][$columnas[$j]]['Tipo'])=='bit' ){
$ALTERCOLUMN.= "ALTER TABLE [".$tablas[$i]."] ALTER COLUMN [".$columnas[$j]."] ".$origen[$tablas[$i]][$columnas[$j]]['Tipo']." ".$origen[$tablas[$i]][$columnas[$j]]['Null'].";\n";
} else {
$ALTERCOLUMN.= "ALTER TABLE [".$tablas[$i]."] ALTER COLUMN [".$columnas[$j]."] ".$origen[$tablas[$i]][$columnas[$j]]['Tipo']." (".$origen[$tablas[$i]][$columnas[$j]]['Tamanio'].") ".$origen[$tablas[$i]][$columnas[$j]]['Null'].";\n";
}
}
} else {
if($origen[$tablas[$i]][$columnas[$j]]['Tamanio']=='-1'){
$origen[$tablas[$i]][$columnas[$j]]['Tamanio']='max';
}
if(trim($origen[$tablas[$i]][$columnas[$j]]['Tipo'])=='int' ||
trim($origen[$tablas[$i]][$columnas[$j]]['Tipo'])=='ntext' ||
trim($origen[$tablas[$i]][$columnas[$j]]['Tipo'])=='bit' ){
//echo "debo crear columna ".$columnas[$j]." en ".$tablas[$i]." \n";
$ADDCOLUMN.= "ALTER TABLE [".$tablas[$i]."] ADD [".$columnas[$j]."] ".$origen[$tablas[$i]][$columnas[$j]]['Tipo']." ".$origen[$tablas[$i]][$columnas[$j]]['Null'].";\n";
} else {
$ADDCOLUMN.= "ALTER TABLE [".$tablas[$i]."] ADD [".$columnas[$j]."] ".$origen[$tablas[$i]][$columnas[$j]]['Tipo']." (".$origen[$tablas[$i]][$columnas[$j]]['Tamanio'].") ".$origen[$tablas[$i]][$columnas[$j]]['Null'].";\n";
}
}
}
}
}
//ahora chequeo al reves!
$tablas=(array_keys($destino));
for ($i=0;$i<count($tablas);$i++){
//me fijo que exista en destino:
if(!array_key_exists($tablas[$i],$origen)){
echo "tabla ".$tablas[$i]." no existe en origen==> debo dropear\n";
} else {
//si existe, asique habra que verificar las columnas!
$columnas=(array_keys($destino[$tablas[$i]]));
for($j=0;$j<count($columnas);$j++){
//me fijo que exista!
if(!array_key_exists($columnas[$j],$origen[$tablas[$i]])){
$DROPCOLUMN.= "ALTER TABLE [".$tablas[$i]."] DROP COLUMN [".$columnas[$j]."];\n";
}
}
}
}
echo $ADDCOLUMN."\n";
echo $DROPCOLUMN."\n";
echo $ALTERCOLUMN."\n";
?>