{"id":18,"date":"2012-08-27T10:20:06","date_gmt":"2012-08-27T13:20:06","guid":{"rendered":"http:\/\/monitor.infracoop.com.ar\/blog2\/?p=18"},"modified":"2012-08-21T00:21:51","modified_gmt":"2012-08-21T03:21:51","slug":"comparando-esquemas","status":"publish","type":"post","link":"https:\/\/www.infracoop.com.ar\/?p=18","title":{"rendered":"Comparando esquemas"},"content":{"rendered":"<p>Hibernate tiene una mala costumbre: si uno lo deja, hace la base de datos como se le ocurre. Qu\u00e9 quiero decir con esto? que si 2 veces le decimos que lo haga, e intentamos comparar los esquemas resultantes, ser\u00e1n distintos, porque no mantiene el \u00f3rden de las columnas dentro de las tablas.<\/p>\n<p>Si el programa va a buscar los datos haciendo selects por nombre de columna, no habr\u00e1 problemas (e hibernate los hace as\u00ed) 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.<\/p>\n<p>Con este panorama (y muchas, muchas tablas que comparar a mano) es que me arm\u00e9 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.<\/p>\n<p>Atenci\u00f3n: NO CHEQUEA FK ni CONSTRAINTS ni INDICES es s\u00f3lo para tablas.<\/p>\n<p>[php]<br \/>\n&lt;?<\/p>\n<p>function db_open($database){<br \/>\n  $serverName = &quot;YourServerHere&quot;;<br \/>\n  $connectionInfo = array( &quot;Database&quot;=&gt;$database);<br \/>\n  $conn = sqlsrv_connect( $serverName, $connectionInfo);<br \/>\n  if( !$conn ) {<br \/>\n    echo &quot;Connection could not be established.\\n&quot;;<br \/>\n    die( print_r( sqlsrv_errors(), true));<br \/>\n  }<br \/>\n  return $conn;<br \/>\n}<\/p>\n<p>function GetArrayTablas($conn){<br \/>\n  $sql=&quot;SELECT so.name AS Tabla, sc.name AS Columna, st.name AS Tipo, sc.max_length AS Tamanio,<br \/>\n        CASE sc.is_nullable<br \/>\n          when 0 then &#8216;NOT NULL&#8217;<br \/>\n          else &#8216;NULL&#8217;<br \/>\n        END AS Nullificable<br \/>\n        FROM sys.objects so INNER JOIN sys.columns sc ON so.object_id = sc.object_id<br \/>\n             INNER JOIN sys.types st ON st.system_type_id = sc.system_type_id AND st.name != &#8216;sysname&#8217;<br \/>\n        WHERE so.type = &#8216;U&#8217; ORDER BY so.name, sc.name&quot;;<\/p>\n<p>  $res=sqlsrv_query($conn,$sql);<br \/>\n  while($row=sqlsrv_fetch_array($res,SQLSRV_FETCH_ASSOC)){<br \/>\n    $miarray[&#8216;Tipo&#8217;]=strtolower($row[&#8216;Tipo&#8217;]) ;<br \/>\n    $miarray[&#8216;Tamanio&#8217;]=strtolower($row[&#8216;Tamanio&#8217;]) ;<br \/>\n    $miarray[&#8216;Null&#8217;]=strtolower($row[&#8216;Nullificable&#8217;]) ;<\/p>\n<p>    if(trim($miarray[&#8216;Tipo&#8217;])==&#8217;nvarchar&#8217;){<br \/>\n      if($miarray[&#8216;Tamanio&#8217;]==510){<br \/>\n        $miarray[&#8216;Tamanio&#8217;]=255;<br \/>\n      } else {<br \/>\n        $miarray[&#8216;Tamanio&#8217;]=($miarray[&#8216;Tamanio&#8217;]\/2);<br \/>\n      }<br \/>\n    }<br \/>\n    $origen[strtolower($row[&#8216;Tabla&#8217;])][strtolower($row[&#8216;Columna&#8217;])]=$miarray;<br \/>\n  }<br \/>\n  return $origen;<br \/>\n}<\/p>\n<p>$conn=db_open(&quot;DbEjemplo&quot;);<br \/>\n$origen=GetArrayTablas($conn);<\/p>\n<p>$conn=db_open(&quot;DbDestino&quot;);<br \/>\n$destino=GetArrayTablas($conn);<\/p>\n<p>\/\/recorro origen, a ver si a destino le falta algo (o hay que modificar algo)<br \/>\n$tablas=(array_keys($origen));<\/p>\n<p>for ($i=0;$i&lt;count($tablas);$i++){<br \/>\n  \/\/me fijo que exista en destino:<br \/>\n  if(!array_key_exists($tablas[$i],$destino)){<br \/>\n    echo &quot;tabla &quot;.$tablas[$i].&quot; no existe en destino==&gt; debo crear!\\n&quot;;<br \/>\n  } else {<br \/>\n    \/\/si existe, asique habra que verificar las columnas!<br \/>\n    $columnas=(array_keys($origen[$tablas[$i]]));<br \/>\n    for($j=0;$j&lt;count($columnas);$j++){<br \/>\n      \/\/me fijo que exista!<br \/>\n      if(array_key_exists($columnas[$j],$destino[$tablas[$i]])){<br \/>\n        \/\/la columna existe!<br \/>\n        \/\/chequeo valores (tipo, tamanio, null)<br \/>\n        $cambio=0;<br \/>\n        \/\/chequeo tipo!<br \/>\n        if($origen[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;]!=$destino[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;]){<br \/>\n          \/\/echo &quot;CAMBIO EL TIPO!\\n&quot;;<br \/>\n          $cambio=1;<br \/>\n        }<br \/>\n        if($origen[$tablas[$i]][$columnas[$j]][&#8216;Tamanio&#8217;]!=$destino[$tablas[$i]][$columnas[$j]][&#8216;Tamanio&#8217;]){<br \/>\n          \/\/echo &quot;CAMBIO EL Tamanio!\\n&quot;;<br \/>\n          if($origen[$tablas[$i]][$columnas[$j]][&#8216;Tamanio&#8217;]==&#8217;-1&#8242;){<br \/>\n            $origen[$tablas[$i]][$columnas[$j]][&#8216;Tamanio&#8217;]=&#8217;max&#8217;;<br \/>\n          }<br \/>\n          $cambio=1;<br \/>\n        }<br \/>\n        if($origen[$tablas[$i]][$columnas[$j]][&#8216;Null&#8217;]!=$destino[$tablas[$i]][$columnas[$j]][&#8216;Null&#8217;]){<br \/>\n          \/\/echo &quot;CAMBIO EL Null!\\n&quot;;<br \/>\n          $cambio=1;<br \/>\n        }<br \/>\n        if($cambio==1){<br \/>\n          if(trim($origen[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;])==&#8217;int&#8217; ||<br \/>\n             trim($origen[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;])==&#8217;ntext&#8217; ||<br \/>\n             trim($origen[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;])==&#8217;bit&#8217; ){<br \/>\n            $ALTERCOLUMN.= &quot;ALTER TABLE [&quot;.$tablas[$i].&quot;] ALTER COLUMN [&quot;.$columnas[$j].&quot;] &quot;.$origen[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;].&quot; &quot;.$origen[$tablas[$i]][$columnas[$j]][&#8216;Null&#8217;].&quot;;\\n&quot;;<br \/>\n          } else {<br \/>\n            $ALTERCOLUMN.= &quot;ALTER TABLE [&quot;.$tablas[$i].&quot;] ALTER COLUMN [&quot;.$columnas[$j].&quot;] &quot;.$origen[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;].&quot; (&quot;.$origen[$tablas[$i]][$columnas[$j]][&#8216;Tamanio&#8217;].&quot;) &quot;.$origen[$tablas[$i]][$columnas[$j]][&#8216;Null&#8217;].&quot;;\\n&quot;;<br \/>\n          }<br \/>\n        }<br \/>\n      } else {<br \/>\n        if($origen[$tablas[$i]][$columnas[$j]][&#8216;Tamanio&#8217;]==&#8217;-1&#8242;){<br \/>\n          $origen[$tablas[$i]][$columnas[$j]][&#8216;Tamanio&#8217;]=&#8217;max&#8217;;<br \/>\n        }<br \/>\n        if(trim($origen[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;])==&#8217;int&#8217; ||<br \/>\n           trim($origen[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;])==&#8217;ntext&#8217; ||<br \/>\n           trim($origen[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;])==&#8217;bit&#8217; ){<br \/>\n          \/\/echo &quot;debo crear columna &quot;.$columnas[$j].&quot; en &quot;.$tablas[$i].&quot; \\n&quot;;<br \/>\n          $ADDCOLUMN.= &quot;ALTER TABLE [&quot;.$tablas[$i].&quot;] ADD [&quot;.$columnas[$j].&quot;] &quot;.$origen[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;].&quot; &quot;.$origen[$tablas[$i]][$columnas[$j]][&#8216;Null&#8217;].&quot;;\\n&quot;;<br \/>\n        } else {<br \/>\n          $ADDCOLUMN.= &quot;ALTER TABLE [&quot;.$tablas[$i].&quot;] ADD [&quot;.$columnas[$j].&quot;] &quot;.$origen[$tablas[$i]][$columnas[$j]][&#8216;Tipo&#8217;].&quot; (&quot;.$origen[$tablas[$i]][$columnas[$j]][&#8216;Tamanio&#8217;].&quot;) &quot;.$origen[$tablas[$i]][$columnas[$j]][&#8216;Null&#8217;].&quot;;\\n&quot;;<br \/>\n        }<br \/>\n      }<br \/>\n    }<br \/>\n  }<br \/>\n}<\/p>\n<p>\/\/ahora chequeo al reves!<\/p>\n<p>$tablas=(array_keys($destino));<br \/>\nfor ($i=0;$i&lt;count($tablas);$i++){<br \/>\n  \/\/me fijo que exista en destino:<br \/>\n  if(!array_key_exists($tablas[$i],$origen)){<br \/>\n    echo &quot;tabla &quot;.$tablas[$i].&quot; no existe en origen==&gt; debo dropear\\n&quot;;<br \/>\n  } else {<br \/>\n    \/\/si existe, asique habra que verificar las columnas!<br \/>\n    $columnas=(array_keys($destino[$tablas[$i]]));<br \/>\n    for($j=0;$j&lt;count($columnas);$j++){<br \/>\n      \/\/me fijo que exista!<br \/>\n      if(!array_key_exists($columnas[$j],$origen[$tablas[$i]])){<br \/>\n        $DROPCOLUMN.= &quot;ALTER TABLE [&quot;.$tablas[$i].&quot;] DROP COLUMN [&quot;.$columnas[$j].&quot;];\\n&quot;;<br \/>\n      }<br \/>\n    }<br \/>\n  }<br \/>\n}<\/p>\n<p>echo $ADDCOLUMN.&quot;\\n&quot;;<br \/>\necho $DROPCOLUMN.&quot;\\n&quot;;<br \/>\necho $ALTERCOLUMN.&quot;\\n&quot;;<br \/>\n?&gt;<br \/>\n[\/php]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hibernate tiene una mala costumbre: si uno lo deja, hace la base de datos como se le ocurre. Qu\u00e9 quiero decir con esto? que si 2 veces&hellip; <span class=\"read-more\"><a class=\"more-link\" href=\"https:\/\/www.infracoop.com.ar\/?p=18\" rel=\"bookmark\">Read more <span class=\"screen-reader-text\">&#8220;Comparando esquemas&#8221;<\/span><\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[7,9,8],"class_list":["post-18","post","type-post","status-publish","format-standard","hentry","category-sqlserver","tag-esquemas","tag-hibernate","tag-php"],"_links":{"self":[{"href":"https:\/\/www.infracoop.com.ar\/index.php?rest_route=\/wp\/v2\/posts\/18","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.infracoop.com.ar\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.infracoop.com.ar\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.infracoop.com.ar\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.infracoop.com.ar\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=18"}],"version-history":[{"count":10,"href":"https:\/\/www.infracoop.com.ar\/index.php?rest_route=\/wp\/v2\/posts\/18\/revisions"}],"predecessor-version":[{"id":35,"href":"https:\/\/www.infracoop.com.ar\/index.php?rest_route=\/wp\/v2\/posts\/18\/revisions\/35"}],"wp:attachment":[{"href":"https:\/\/www.infracoop.com.ar\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=18"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.infracoop.com.ar\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=18"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.infracoop.com.ar\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=18"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}