{"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<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?\r\n\r\nfunction db_open($database){\r\n  $serverName = &quot;YourServerHere&quot;;\r\n  $connectionInfo = array( &quot;Database&quot;=&gt;$database);\r\n  $conn = sqlsrv_connect( $serverName, $connectionInfo);\r\n  if( !$conn ) {\r\n    echo &quot;Connection could not be established.\\n&quot;;\r\n    die( print_r( sqlsrv_errors(), true));\r\n  }\r\n  return $conn;\r\n}\r\n\r\nfunction GetArrayTablas($conn){\r\n  $sql=&quot;SELECT so.name AS Tabla, sc.name AS Columna, st.name AS Tipo, sc.max_length AS Tamanio,\r\n        CASE sc.is_nullable\r\n          when 0 then 'NOT NULL'\r\n          else 'NULL'\r\n        END AS Nullificable\r\n        FROM sys.objects so INNER JOIN sys.columns sc ON so.object_id = sc.object_id\r\n             INNER JOIN sys.types st ON st.system_type_id = sc.system_type_id AND st.name != 'sysname'\r\n        WHERE so.type = 'U' ORDER BY so.name, sc.name&quot;;\r\n\r\n  $res=sqlsrv_query($conn,$sql);\r\n  while($row=sqlsrv_fetch_array($res,SQLSRV_FETCH_ASSOC)){\r\n    $miarray&#x5B;'Tipo']=strtolower($row&#x5B;'Tipo']) ;\r\n    $miarray&#x5B;'Tamanio']=strtolower($row&#x5B;'Tamanio']) ;\r\n    $miarray&#x5B;'Null']=strtolower($row&#x5B;'Nullificable']) ;\r\n\r\n    if(trim($miarray&#x5B;'Tipo'])=='nvarchar'){\r\n      if($miarray&#x5B;'Tamanio']==510){\r\n        $miarray&#x5B;'Tamanio']=255;\r\n      } else {\r\n        $miarray&#x5B;'Tamanio']=($miarray&#x5B;'Tamanio']\/2);\r\n      }\r\n    }\r\n    $origen&#x5B;strtolower($row&#x5B;'Tabla'])]&#x5B;strtolower($row&#x5B;'Columna'])]=$miarray;\r\n  }\r\n  return $origen;\r\n}\r\n\r\n$conn=db_open(&quot;DbEjemplo&quot;);\r\n$origen=GetArrayTablas($conn);\r\n\r\n$conn=db_open(&quot;DbDestino&quot;);\r\n$destino=GetArrayTablas($conn);\r\n\r\n\/\/recorro origen, a ver si a destino le falta algo (o hay que modificar algo)\r\n$tablas=(array_keys($origen));\r\n\r\nfor ($i=0;$i&lt;count($tablas);$i++){\r\n  \/\/me fijo que exista en destino:\r\n  if(!array_key_exists($tablas&#x5B;$i],$destino)){\r\n    echo &quot;tabla &quot;.$tablas&#x5B;$i].&quot; no existe en destino==&gt; debo crear!\\n&quot;;\r\n  } else {\r\n    \/\/si existe, asique habra que verificar las columnas!\r\n    $columnas=(array_keys($origen&#x5B;$tablas&#x5B;$i]]));\r\n    for($j=0;$j&lt;count($columnas);$j++){\r\n      \/\/me fijo que exista!\r\n      if(array_key_exists($columnas&#x5B;$j],$destino&#x5B;$tablas&#x5B;$i]])){\r\n        \/\/la columna existe!\r\n        \/\/chequeo valores (tipo, tamanio, null)\r\n        $cambio=0;\r\n        \/\/chequeo tipo!\r\n        if($origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo']!=$destino&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo']){\r\n          \/\/echo &quot;CAMBIO EL TIPO!\\n&quot;;\r\n          $cambio=1;\r\n        }\r\n        if($origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tamanio']!=$destino&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tamanio']){\r\n          \/\/echo &quot;CAMBIO EL Tamanio!\\n&quot;;\r\n          if($origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tamanio']=='-1'){\r\n            $origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tamanio']='max';\r\n          }\r\n          $cambio=1;\r\n        }\r\n        if($origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Null']!=$destino&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Null']){\r\n          \/\/echo &quot;CAMBIO EL Null!\\n&quot;;\r\n          $cambio=1;\r\n        }\r\n        if($cambio==1){\r\n          if(trim($origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo'])=='int' ||\r\n             trim($origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo'])=='ntext' ||\r\n             trim($origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo'])=='bit' ){\r\n            $ALTERCOLUMN.= &quot;ALTER TABLE &#x5B;&quot;.$tablas&#x5B;$i].&quot;] ALTER COLUMN &#x5B;&quot;.$columnas&#x5B;$j].&quot;] &quot;.$origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo'].&quot; &quot;.$origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Null'].&quot;;\\n&quot;;\r\n          } else {\r\n            $ALTERCOLUMN.= &quot;ALTER TABLE &#x5B;&quot;.$tablas&#x5B;$i].&quot;] ALTER COLUMN &#x5B;&quot;.$columnas&#x5B;$j].&quot;] &quot;.$origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo'].&quot; (&quot;.$origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tamanio'].&quot;) &quot;.$origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Null'].&quot;;\\n&quot;;\r\n          }\r\n        }\r\n      } else {\r\n        if($origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tamanio']=='-1'){\r\n          $origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tamanio']='max';\r\n        }\r\n        if(trim($origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo'])=='int' ||\r\n           trim($origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo'])=='ntext' ||\r\n           trim($origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo'])=='bit' ){\r\n          \/\/echo &quot;debo crear columna &quot;.$columnas&#x5B;$j].&quot; en &quot;.$tablas&#x5B;$i].&quot; \\n&quot;;\r\n          $ADDCOLUMN.= &quot;ALTER TABLE &#x5B;&quot;.$tablas&#x5B;$i].&quot;] ADD &#x5B;&quot;.$columnas&#x5B;$j].&quot;] &quot;.$origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo'].&quot; &quot;.$origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Null'].&quot;;\\n&quot;;\r\n        } else {\r\n          $ADDCOLUMN.= &quot;ALTER TABLE &#x5B;&quot;.$tablas&#x5B;$i].&quot;] ADD &#x5B;&quot;.$columnas&#x5B;$j].&quot;] &quot;.$origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tipo'].&quot; (&quot;.$origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Tamanio'].&quot;) &quot;.$origen&#x5B;$tablas&#x5B;$i]]&#x5B;$columnas&#x5B;$j]]&#x5B;'Null'].&quot;;\\n&quot;;\r\n        }\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\n\/\/ahora chequeo al reves!\r\n\r\n$tablas=(array_keys($destino));\r\nfor ($i=0;$i&lt;count($tablas);$i++){\r\n  \/\/me fijo que exista en destino:\r\n  if(!array_key_exists($tablas&#x5B;$i],$origen)){\r\n    echo &quot;tabla &quot;.$tablas&#x5B;$i].&quot; no existe en origen==&gt; debo dropear\\n&quot;;\r\n  } else {\r\n    \/\/si existe, asique habra que verificar las columnas!\r\n    $columnas=(array_keys($destino&#x5B;$tablas&#x5B;$i]]));\r\n    for($j=0;$j&lt;count($columnas);$j++){\r\n      \/\/me fijo que exista!\r\n      if(!array_key_exists($columnas&#x5B;$j],$origen&#x5B;$tablas&#x5B;$i]])){\r\n        $DROPCOLUMN.= &quot;ALTER TABLE &#x5B;&quot;.$tablas&#x5B;$i].&quot;] DROP COLUMN &#x5B;&quot;.$columnas&#x5B;$j].&quot;];\\n&quot;;\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\necho $ADDCOLUMN.&quot;\\n&quot;;\r\necho $DROPCOLUMN.&quot;\\n&quot;;\r\necho $ALTERCOLUMN.&quot;\\n&quot;;\r\n?&gt;\r\n<\/pre>\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}]}}