Los campos insertados se truncan en 1024 caracteres

Al crear un TableAdapter en una aplicación de ASP.NET 2 usando Visual Web Developer 2005 Express, se establecen algunos límites que no son obvios a primera vista.

En un proyecto en el que trabajo tengo una base de datos en MySQL con un campo llamado Cuerpo que es de tipo longtext y está diseñado para que pueda almacenar varios párrafos de HTML.

Al crear el TableAdapter y el Business Logic uno nunca establece los tamaños de los campos, ya que la herramienta lo hace por uno mismo.

En mi caso, al insertar un registro mediante mi aplicación, el campo Cuerpo se truncaba, almacenando únicamente alrededor de 1000 o 1024 caracteres.

Mi primera idea fue ir a revisar mi tabla de MySQL, pero el límite no estaba ahí. En seguida fui a ver las propiedades de la tabla en el TableAdapter de mi aplicación:

Propiedades

Como puedes ver, el MaxLength del campo en cuestión estaba establecido en 60,000, así que tampoco estaba ahí el problema. Después de un rato de darle vueltas al asunto, se me ocurrió ver las propiedades de la sentencia que hacía el insert en la base de datos, la cual en mi ejemplo se llama InsertaEnvio. Solamente hay que seleccionarla y oprimir el pequeño botón con tres puntos:

TableAdapter

Se mostrará la ventana de propiedades de la sentencia SQL. Seleccioné el campo problemático, y noté que en la propiedad Size tenía un valor de 1024:

Tamano del campo

Listo, ahí estaba el error, solamente lo modifiqué a un valor lo suficientemente grande:

Tamano modificado

Salve el archivo xsd, probé nuevamente, y el problema desapareció.

SQL que encuentra coincidencias de un string sin usar LIKE en un .XSD de ASP.NET 2

Estoy usando .NET 2. Tengo mi archivo .XSD (Data Layer) y mi Business Logic.

El caso es que en el .XSD estoy poniendo esta consulta:

SELECT * from tabla where nombre LIKE ?

Yo quería encontrar cualquier campo que contuviera el string solicitado, es decir, si alguien buscaba “pa”, la sentencia debía regresar valores como “paco”, “palabra”, “pais”, etc. Pero con el LIKE solamente regresaba el valor si la coincidencia era exacta.

Otros intentos que hice fueron:

SELECT * from tabla where nombre LIKE '%?%'

SELECT * from tabla where nombre LIKE %?%

SELECT * from tabla where nombre LIKE %?%

Ninguno sirve porque al parecer al definir la sentencia SQL en el archivo .XSD, el signo de interrogación no puede tener ningún comodín.

Entonces busqué alguna función que pudiera ayudarme, y al final lo logré. La sentencia debe quedar así:

SELECT * from tabla where (INSTR(nombre,?) > 0)

INSTR(str,substr) devuelve la posición de la primera ocurrencia de substring en la cadena de texto str.

Así que si devuelve un número mayor a cero, significa que lo encontró.

Ahora bien, siendo más estrictos, lo que yo quería era que encontrara el principio de la palabra. Es decir, si alguien buscaba por “yo” debería encontrar “yolanda”, pero no “pelayo”. Entonces necesitaba algo que le indicara que buscara solamente al principio del campo.

Así es como lo logré:

SELECT * from tabla where nombre REGEXP CONCAT('^',?)

expr REGEXP pat realiza una búsqueda de expresiones regulares en la cadena expr usando el modelo pat.

CONCAT(cad1, cad2, ...) une cadenas de texto.

Es decir que al ejecutarse:
SELECT * from tabla where nombre REGEXP CONCAT('^','yo')

Se convierte en:
SELECT * from tabla where nombre REGEXP '^yo'

Como sabes, el símbolo ^ en expresiones regulares, significa el inicio de una palabra.

El signo ‘?’ es por si estás utilizando MySQL.

Si utilizas SQL Server, cambia el ‘?’ por ‘@Nombre’ o cualquiera que sea el nombre de tu parámetro.

Para mayor información:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html

Cómo mostrar los n primeros registros de una tabla o consulta

En ocasiones es necesario mostrar los n primeros registros de una tabla o consulta.

Supón que tienes una base de datos donde guardas un historial de noticias. Quieres mostrar en la portada de tu sitio web las 5 noticias más recientes. Es sencillo realizar una consulta que te devuelva todas las noticias ordenadas por fecha descendente, pero solamente necesitas las 5 primeras.

Para hacerlo en mySQL se utiliza LIMIT

Sintaxis:

SELECT * FROM tabla LIMIT x, y

Donde:
x es el renglón a partir del cual se devolverá. El primer renglón es 0, no 1.
y es la cantidad de registros a devolver.

De tal manera que:

SELECT * FROM tabla LIMIT 0, 5

devuelve los primeros cinco renglones a partir del primero. Es decir, los renglones 0, 1, 2, 3 y 4.

SELECT * FROM tabla LIMIT 5, 10

devuelve 10 renglones a partir del sexto, es decir, los renglones 6, 7, 8, 9, 10, 11, 12, 13, 14 y 15.

Regresando al caso que planteado al inicio de este post, la sentencia SQL quedaría asi:

SELECT * FROM noticias ORDER BY fecha DESC LIMIT 0,5

Para una referencia completa visita:
http://dev.mysql.com/doc/refman/5.0/es/select.html

Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints

Este error ya ha aparecido en dos de mis proyectos.

Tenía un Datalist (o Gridview) que estaba ligado a un ObjectDatasource, el cual se alimentaba de un Business Layer que a su vez tomaba los datos de un archivo XSD.

Estuve peléandome con todos estos objetos, checando sus propiedades, borrándolos y volviéndolos a crear, y nada funcionó.

En las dos ocasiones que se me presentó esta situación, resulta que el problema estaba en los datos!

En ambas ocasiones estaba convirtiendo la aplicación de ASP.NET 1 a ASP.NET 2, por lo que ya contaba con la base de datos y ésta ya tenia información real.

Así es que si no encuentras el problema en la lógica, checa también los datos. En uno de los casos pasaba que había un campo de fecha, el cual tenía muchos registros que tenían la fecha establecida en “0000-00-00”, es decir, no la habían capturado porque era un campo que quedó en desuso y no tuve la precisión de eliminarlo o llenarlo con una fecha válida.

El caso es que cuando la aplicación trataba de llenar el DataList, se encontraba con esa fecha inválida y regresaba el error:

Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.

Mi solución: llené todos esos campos con fechas válidas y funcionó.

Repito, pasa muchas veces, si no encuentras el error en tu lógica, siempre revisa la validez de los datos en la base de datos.

Actualización

Me volvió a suceder el mismo error, y encontré una razón más contundente.

Resulta que mi sentencia SQL hacía un join de tres tablas. Estaba intentando colocar esa sentencia en un TableAdapter que había creado para una de las tablas:

TableAdapter para una sola tabla

El TableAdapter mostrado arriba contiene la definición de una tabla, es por eso que se pueden leer los campos id, idPostal, idusuario, etc.

Al ejecutar el join se mostraba el error descrito en la primera parte de este post.

Para solucionar esta situación tuve que pasar la sentencia que contenía el join a un nuevo TableAdapter, como se muestra a continuación:

TableAdapter para un join de varias tablas

Listo, como puedes ver el TableAdapter creado ya no contiene toda la definición de las columnas. Le cree una clase BusinessLogic la cual uso en mi código y ya no marca esos problemas. 🙂

Segunda Actualización

En otros casos puede ser la propiedad MaxLength. Por ejemplo, si en tu TableAdapter tienes esa propiedad establecida en un valor distinto al que aparece para ese mismo campo en las sentencias Insert o Update, también ocurre este error. Todos los MaxLength para el mismo campo deben ser iguales para todas las sentencias y para las propiedades mismas del adaptador.