Mostrando entradas con la etiqueta SQL. Mostrar todas las entradas
Mostrando entradas con la etiqueta SQL. Mostrar todas las entradas

martes, 16 de diciembre de 2014

Problemas en SQL Server con el caracter ª

Por si se les presenta en alguna ocasión este problema, aquí les dejo la solución.

Resulta que estaba intentando hacer la siguiente consulta en SQL Server 2012, en una Base de Datos con Intercalación "Modern_Spanish_CI_AI".

SELECT * FROM tabla WHERE name like '%'ª'%'

He incluso probé con el código ASCII de  ª que es el 170

SELECT * FROM tabla WHERE name like '%'+char(170)+'%'

Pero al ejecutar la consulta me devolvía nombres con "a", la solución para casos como estos es, colocarle COLLATE Latin1_General_CI_AS


SELECT * FROM tabla WHERE name like '%'ª'%'  COLLATE Latin1_General_CI_AS

Y así muestra los resultados esperados, ver además:

Códigos ASCII: http://ascii.cl/es/codigos-html.htm

Consulta SQL que devuelve el símbolo y su código ASCII:

DECLARE @nstring nchar(8);
SET @nstring = '-ª';
SELECT UNICODE(SUBSTRING(@nstring, 2, 1)) as codigoASCII_Dec, 
   NCHAR(UNICODE(SUBSTRING(@nstring, 2, 1))) as simbolo;
GO

martes, 10 de abril de 2012

Trabajo con Fechas PHP, MYSQL

Cuando los programadores tenemos que realizar una página web donde se trabaja con Fechas, siempre nos enfrentamos a problemas de formato, ya sea por la forma en que MySQL almacena los tipo "DATE", o la forma en que se quiere mostrar la fecha al usuario.

Casualmente hoy, me ha dado un error que he logrado solucionar, lo comento por si les pasa ya tengan la solución.

Primero, hacerles un breve resumen de la situación:

 Como todos saben MYSQL almacena lor registros de tipo DATE en formato "YYYY-MM-DD" (Año-Mes-Dia), por ejemplo, (2012-04-10): Fechas ISO 8601. 

Imaginemos que queremos realizar una consulta para extraer de la tabla "tusuario" la fecha de nacimiento de todos los usuarios de la tabla:

SELECT tusuario.fechaNacimiento FROM tusuario.

Si esta consulta la escribimos dentro de un fichero PHP:

require_once(conexionBD.php"); //para llamar al archivo que ejecuta la conexión a la BD.
$sql="SELECT tusuario.fechaNacimiento FROM tusuario";
$consulta=mysql_query($sql, $conexion) or die (mysql_error()); //crea conexión
 if(mysql_num_rows($consulta)>0){
      while($fila=mysql_fetch_array($consulta)){
             echo $fila[fechaNacimiento];
      }
}
 En pantalla se mostrará la fecha en formato "YYYY-MM-DD"; ahora bien, si el usuario final desea que le fecha se muestre en formato "DD/MM/YYYY" en muchos sitios se recomienda utilizar la siguiente función

echo (date(("d/m/Y"),strtotime( $fila[fechaNacimiento])));
VER: strtotime

Sin embargo, cuando utilicé dicha función, me devolvía la fecha "01/01/1970" para todos los casos, por tanto comencé a buscar opciones e hice lo siguiente:

 list($anno, $mes, $dia) = explode('-', $fila[fechaProximaLlamada]);
echo "$dia/$mes/$anno";
 Y de esa forma salieron las fechas con el formato adecuado.

Por el contrario, si queremos almacenar la fecha en nuestra BD y se ecnuentra en formato DD/MM/YYYY lo que tenemos que hacer para cambiarla es lo siguiente:

$fechaNacimiento=$_GET["fechaNacimiento"]; //En caso de que se reciba por GET o por POST
 $partes=explode("/", $fechaNacimiento);
 $fecha=$partes[2]."-".$partes[1]."-".$partes[0]; //para que la fecha se guarde en la BD como YYYY-MM-DD 

jueves, 5 de abril de 2012

Relaciones entre tablas PHPMyAdmin

PHPMyAdmin nos permite crear relaciones entre tablas. Para ello, abrir una tabla y seleccionar la pestaña "Estructura". En esa ventana aparecerá la opción "Vista de Relaciones".

Antes de comenzar asegúrese de estar usando el Motor de almacenamiento INNODB (que es el que soporta las relaciones), para ello la pestaña "Operaciones" les muestra en "Opciones de la tabla" el dato anteriormente mencionado.

Volviendo a la vista de relaciones, podrá seleccionar la llave foránea correspondiente, permitiendo hacer cambios en cascada al agregar o eliminar registros en nuestra base de datos asi como conservar integridad de la información almacenada en ella.

La integridad de datos es importante ya que no permite tener incoherencia en la información o falta de ella, permitiendo que todos los datos estén relacionados en nuestra Base de datos.

Por lo general, cuando se selecciona el índice destino para la relación y las acciones correspondientes de "ON DELETE" y "ON UPDATE" se selecciona la opción "CASCADE" que permite actualizar los valores. Lo que significa que si una fila en la tabla padre es eliminada, entonces se eliminarán las filas de la tabla hijo cuya clave foránea sea igual al valor de la clave referenciada en la tabla padre.

También se encuentran las opciones siguientes:

  • SET NULL: Actualiza los valores relacionados a "null". Requiere que el campo indicado en FOREIGN KEY permita valores nulos. Si está definido con flag NOT NULL daría un mensaje de error. 
  • NO ACTION: no realiza ninguna acción.
  • RESTRICT: restringe o impide que se ejecuten acciones.

Un error frecuente que suele aparecer es "#1452 - Cannot add or update a child row: a foreign key constraint fails"

La respuesta la suele tener la "integridad referencial" (Por ejemplo, Si cargas la tabla B, pero en esa tabla un campo es FK de la tabla A, hasta que la tabla A no tenga en su PK el valor correspondiente que usarás en B, no puedes cargar la tabla B).

La integridad referencial ha de establecerse siempre entre dos tablas. Una de ellas ha de comportarse como tabla principal o tabla padre y la otra sería la tabla vinculada o tabla hijo. Siendo necesario que::
  •  La tabla padre tenga un índice primario (PRIMARY KEY)
  • La tabla hijo tenga un índice (no es necesario que sea ni único ni primario) asociado a campos de tipo idéntico a los que se usen para índice de la tabla principal.

El error #1452 de MySQL ocurrirá si se intenta añadir un registro a la tabla hijo sin que exista el campo en la tabla padre. Por tanto, tenemos que añadir primero el registro en la tabla padre y luego en la tabla hijo.  
Es importante señalar que en la columna que se estableció como índice podemos insertar duplicados ya que no establecimos la condición de índice PRIMARIO ó UNICO.

Del tema "integridad referencial" hablaré más adelante.

Vista Indexada


Mejorar el rendimiento de una vista.

Si al ejecutar una vista demora en devolver los resultados, una solución podría ser hacerla indexada, para que guarde la información y no tenga que unir todas las tablas que componen la vista cada vez.

Los índices se utilizan para buscar las filas con valores de columna específica rápidamente. Sin un índice, MySQL debe comenzar con el primer registro y luego leer a través de toda la tabla para buscar las filas correspondientes, y si la tabla es muy grande este proceso se demorará más.

Si la tabla tiene un índice para las columnas que se trate, MySQL puede determinar rápidamente la posición de buscar en el medio del archivo de datos sin tener que mirar todos los datos. Por tanto, los índices aumentan la velocidad de la consulta y si no están bien configurados o no se tienen, puede traer como consecuencia el bloqueo de MYSQL, que la Web vaya lenta o incluso que el servidor se bloque o se caiga.

En caso de que la consulta SQL continúe lenta y no se pueda solucionar mediante una vista indexada, habría que pensar en hacer Triggers.

Los índices se crearían en los campos que se utilizan para unir tablas (por ejemplo, si en una tabla se usa el idUsuario para unirlo con la otra que también tiene idUsuario, se crearían dos índices, ambos con idUsuario, para que la BD pueda unir las tablas más rápidamente). Esto sólo es necesario en caso de que no sean campos de clave primaria, ya que éstos se indexan automáticamente. Creo que se ganaría bastante si en las uniones se están usando campos que no son clave primaria...

Se puede probar a crear los índices de las tablas de una vista, porque eso se haría rápido (si por ejemplo una vista une 5 tablas, sería crear 5 índices o pocos más) y es fácil de comprobar si va bien o no. Y si no funciona o no optimiza lo suficiente, pues hay que intentar lo otro.

Problemas encontrados:

  • En SQL SERVER 2005, por ejemplo, si hay tablas que se unen con OUTER JOIN no es posible tenerlo en vistas indexadas ya que las filas pueden desaparecer de forma lógica de una vista indizada basada en OUTER JOIN cuando inserte datos en una tabla de base. Esto hace que las vistas OUTER JOIN que son relativamente complejas de implementar se actualicen de forma incremental y el rendimiento de la implementación sería más lento que para las vistas basadas en (INNER) JOIN estándar.
  • Hay ocasiones que si en vez de utilizar OUTER JOIN utilizamos INNER JOIN nos devolve menos registros de los que necesitamos.
  • Otro problema es la dependencia de vistas con otras vistas. Es decir, si tengo una vista definida sobre otra vista. SQL Server no permite indizar la vista del nivel superior. En este artículo (http://www.microsoft.com/latam/technet/productos/servers/sql/2005/impprfiv.mspx) dicen que hay que expandir la definición de la vista anidada a mano en la vista del nivel superior y luego crear un índice, indizando la vista interna o no.