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"; ?>