Entonces, según la respuesta de Mehrdad a una pregunta relacionada , entiendo que una columna de tabla de base de datos "adecuada" no almacena una lista. Más bien, debe crear otra tabla que contenga efectivamente los elementos de dicha lista y luego vincularla directamente o mediante una tabla de unión. Sin embargo, el tipo de lista que quiero crear estará compuesto por elementos únicos (a diferencia de la fruta de la pregunta vinculadaejemplo). Además, los elementos de mi lista están ordenados explícitamente, lo que significa que si almacenaba los elementos en otra tabla, tendría que ordenarlos cada vez que acceda a ellos. Finalmente, la lista es básicamente atómica en el sentido de que cada vez que desee acceder a la lista, querré acceder a la lista completa en lugar de solo a una parte de ella, por lo que parece una tontería tener que emitir una consulta de base de datos para recopilar partes de la lista.
La solución de AKX (vinculada arriba) es serializar la lista y almacenarla en una columna binaria. Pero esto también parece inconveniente porque significa que tengo que preocuparme por la serialización y deserialización.
¿Existe alguna solución mejor? Si no es ninguna solución mejor, entonces ¿por qué? Parece que este problema debería surgir de vez en cuando.
... solo un poco más de información para que sepas de dónde vengo. Tan pronto como comencé a comprender SQL y las bases de datos en general, me encendí con LINQ to SQL, y ahora estoy un poco malcriado porque espero lidiar con mi modelo de objetos de programación sin tener que pensar en cómo los objetos son consultados o almacenados en la base de datos.
¡Gracias a todos!
Juan
ACTUALIZACIÓN: Entonces, en la primera oleada de respuestas que obtengo, veo "puedes ir por la ruta CSV / XML ... ¡pero NO HAGAS!". Así que ahora estoy buscando explicaciones de por qué. Indícame algunas buenas referencias.
Además, para darte una mejor idea de lo que estoy haciendo: En mi base de datos tengo una tabla de funciones que tendrá una lista de pares (x, y). (La tabla también tendrá otra información que no tiene importancia para nuestra discusión). Nunca necesitaré ver parte de la lista de pares (x, y). Más bien, los tomaré todos y los trazaré en la pantalla. Permitiré que el usuario arrastre los nodos para cambiar los valores ocasionalmente o agregar más valores al gráfico.
Puede simplemente olvidarse de SQL por completo e ir con un enfoque "NoSQL". RavenDB , MongoDB y CouchDB vienen a la mente como posibles soluciones. Con un enfoque NoSQL, no está utilizando el modelo relacional ... ni siquiera está limitado a esquemas.
fuente
Lo que he visto hacer a mucha gente es esto (puede que no sea el mejor enfoque, corrígeme si me equivoco):
La tabla que estoy usando en el ejemplo se muestra a continuación (la tabla incluye apodos que le ha dado a sus novias específicas. Cada novia tiene una identificación única):
Supongamos que desea almacenar muchos apodos bajo una identificación. Por eso hemos incluido un
seq_no
campo.Ahora, complete estos valores en su tabla:
Si desea encontrar todos los nombres que le ha dado a su novia id 1, puede usar:
fuente
Respuesta simple: si, y solo si, está seguro de que la lista siempre se usará como una lista, entonces únase a la lista al final con un carácter (como '\ 0') que no se usará en el mensaje de texto nunca, y almacenarlo. Luego, cuando lo recupere, puede dividirlo por '\ 0'. Por supuesto, hay otras formas de hacer esto, pero dependen de su proveedor de base de datos específico.
Como ejemplo, puede almacenar JSON en una base de datos de Postgres. Si su lista es de texto y solo quiere la lista sin más problemas, ese es un compromiso razonable.
Otros han aventurado sugerencias de serialización, pero realmente no creo que serializar sea una buena idea: parte de lo bueno de las bases de datos es que varios programas escritos en diferentes lenguajes pueden comunicarse entre sí. Y los programas serializados usando el formato de Java no funcionarían tan bien si un programa Lisp quisiera cargarlo.
Si desea una buena manera de hacer este tipo de cosas, generalmente hay tipos de matrices o similares disponibles. Postgres, por ejemplo, ofrece una matriz como un tipo y le permite almacenar una matriz de texto, si eso es lo que desea , y existen trucos similares para MySql y MS SQL usando JSON, y DB2 de IBM también ofrece un tipo de matriz (en su propia documentación útil ). Esto no sería tan común si no fuera necesario.
Lo que pierdes al seguir ese camino es la noción de la lista como un montón de cosas en secuencia. Al menos nominalmente, las bases de datos tratan los campos como valores únicos. Pero si eso es todo lo que quieres, entonces deberías hacerlo. Es un juicio de valor que tienes que hacer por ti mismo.
fuente
Además de lo que han dicho todos los demás, le sugiero que analice su enfoque en términos más largos que ahora. Es actualmente el caso de que los artículos son únicos. Es actualmente el caso de que el recurso a los artículos requeriría una nueva lista. Es casi necesario que la lista sea actualmente corta. Aunque no tengo los detalles del dominio, no es muy exagerado pensar que esos requisitos podrían cambiar. Si serializa su lista, está horneando con una inflexibilidad que no es necesaria en un diseño más normalizado. Por cierto, eso no significa necesariamente una relación Many: Many completa. Podría tener una única tabla secundaria con una clave externa para el padre y una columna de caracteres para el elemento.
Si aún desea seguir este camino de serializar la lista, podría considerar almacenar la lista en XML. Algunas bases de datos, como SQL Server, incluso tienen un tipo de datos XML. La única razón por la que sugeriría XML es que, casi por definición, esta lista debe ser corta. Si la lista es larga, serializarla en general es un enfoque terrible. Si sigue la ruta CSV, debe tener en cuenta los valores que contienen el delimitador, lo que significa que está obligado a utilizar identificadores entre comillas. Suponiendo que las listas son cortas, probablemente no hará mucha diferencia si usa CSV o XML.
fuente
Simplemente lo almacenaría como CSV, si se trata de valores simples, entonces debería ser todo lo que necesita (XML es muy detallado y la serialización hacia / desde él probablemente sería excesivo, pero esa también sería una opción).
Aquí hay una buena respuesta sobre cómo extraer archivos CSV con LINQ.
fuente
Si necesita realizar una consulta en la lista, guárdelo en una tabla.
Si siempre desea la lista, puede almacenarla como una lista delimitada en una columna. Incluso en este caso, a menos que tenga razones MUY específicas para no hacerlo, guárdelo en una tabla de búsqueda.
fuente
Solo una opción no se menciona en las respuestas. Puede desnormalizar su diseño de base de datos. Entonces necesitas dos mesas. Una tabla contiene la lista adecuada, un elemento por fila, otra tabla contiene la lista completa en una columna (separada por coma, por ejemplo).
Aquí está el diseño de base de datos 'tradicional':
Aquí está la tabla desnormalizada:
La idea aquí: mantienes la tabla de Listas usando desencadenadores o código de aplicación. Cada vez que modifica el contenido de List_Item, las filas correspondientes en Lists se actualizan automáticamente. Si lee principalmente listas, podría funcionar bastante bien. Ventajas: puede leer listas en una sola declaración. Contras: las actualizaciones requieren más tiempo y esfuerzo.
fuente
Si realmente desea almacenarlo en una columna y poder consultarlo, muchas bases de datos ahora admiten XML. Si no está consultando, puede almacenarlos como valores separados por comas y analizarlos con una función cuando los necesite separados. Estoy de acuerdo con todos los demás, sin embargo, si está buscando usar una base de datos relacional, una gran parte de la normalización es la separación de datos como ese. Sin embargo, no estoy diciendo que todos los datos se ajusten a una base de datos relacional. Siempre puede buscar otros tipos de bases de datos si muchos de sus datos no se ajustan al modelo.
fuente
Creo que en ciertos casos, puede crear una "lista" FALSA de elementos en la base de datos, por ejemplo, la mercancía tiene algunas imágenes para mostrar sus detalles, puede concatenar todas las ID de imágenes divididas por comas y almacenar la cadena en la base de datos, entonces solo necesita analizar la cadena cuando la necesite. Ahora estoy trabajando en un sitio web y planeo usarlo de esta manera.
fuente
Estaba muy reacio a elegir el camino que finalmente decidí tomar debido a muchas respuestas. Si bien añaden más comprensión a lo que es SQL y sus principios, decidí convertirme en un forajido. También dudé en publicar mis hallazgos, ya que para algunos es más importante desahogar la frustración con alguien que rompe las reglas en lugar de comprender que hay muy pocas verdades universales.
Lo probé ampliamente y, en mi caso específico, fue mucho más eficiente que usar el tipo de matriz (ofrecido generosamente por PostgreSQL) o consultar otra tabla.
Aquí está mi respuesta: he implementado con éxito una lista en un solo campo en PostgreSQL, haciendo uso de la longitud fija de cada elemento de la lista. Digamos que cada elemento es un color como valor hexadecimal ARGB, significa 8 caracteres. Por lo tanto, puede crear su matriz de un máximo de 10 elementos multiplicando por la longitud de cada elemento:
En caso de que la longitud de los elementos de su lista difiera, siempre puede llenar el relleno con \ 0
NB: Obviamente, este no es necesariamente el mejor enfoque para el número hexadecimal, ya que una lista de enteros consumiría menos almacenamiento, pero esto es solo con el propósito de ilustrar esta idea de matriz haciendo uso de una longitud fija asignada a cada elemento.
La razón por la cual: 1 / Muy conveniente: recupere el elemento i en la subcadena i * n, (i +1) * n. 2 / Sin gastos generales de consultas de tablas cruzadas. 3 / Más eficiente y económico en el lado del servidor. La lista es como un mini blob que el cliente tendrá que dividir.
Si bien respeto a las personas que siguen las reglas, muchas explicaciones son muy teóricas y, a menudo, no reconocen que, en algunos casos específicos, especialmente cuando se busca un costo óptimo con soluciones de baja latencia, algunos ajustes menores son más que bienvenidos.
"Dios no quiera que esté violando algún principio sagrado y sagrado de SQL": Adoptar un enfoque más abierto y pragmático antes de recitar las reglas es siempre el camino a seguir. De lo contrario, podrías terminar como un fanático sincero recitando las Tres leyes de la robótica antes de ser aniquilado por Skynet.
No pretendo que esta solución sea un gran avance, ni que sea ideal en términos de legibilidad y flexibilidad de la base de datos, pero ciertamente puede darle una ventaja cuando se trata de latencia.
fuente
Muchas bases de datos SQL permiten que una tabla contenga una subtabla como componente. El método habitual es permitir que el dominio de una de las columnas sea una tabla. Esto se suma al uso de alguna convención como CSV para codificar la subestructura de formas desconocidas para el DBMS.
Cuando Ed Codd estaba desarrollando el modelo relacional en 1969-1970, definió específicamente una forma normal que no permitiría este tipo de anidamiento de tablas. La forma normal se denominó más tarde Primera forma normal. Luego pasó a mostrar que para cada base de datos, hay una base de datos en la primera forma normal que expresa la misma información.
¿Por qué molestarse con esto? Bueno, las bases de datos en la primera forma normal permiten el acceso con clave a todos los datos. Si proporciona un nombre de tabla, un valor clave en esa tabla y un nombre de columna, la base de datos contendrá como máximo una celda que contenga un elemento de datos.
Si permite que una celda contenga una lista, una tabla o cualquier otra colección, ahora no puede proporcionar acceso con clave a los subelementos sin reelaborar por completo la idea de una clave.
El acceso con clave a todos los datos es fundamental para el modelo relacional. Sin este concepto, el modelo no es relacional. En cuanto a por qué el modelo relacional es una buena idea y cuáles podrían ser las limitaciones de esa buena idea, hay que mirar los 50 años de experiencia acumulada con el modelo relacional.
fuente
puede almacenarlo como texto que parece una lista y crear una función que pueda devolver sus datos como una lista real. ejemplo:
base de datos:
Y la función del compilador de listas (escrita en Python, pero debería ser fácilmente traducible a la mayoría de los otros lenguajes de programación). TEXT representa el texto cargado desde la tabla sql. devuelve la lista de cadenas de la cadena que contiene la lista. si desea que devuelva ints en lugar de cadenas, haga que el modo sea igual a 'int'. Lo mismo ocurre con 'string', 'bool' o 'float'.
También aquí hay una función de lista a cadena en caso de que la necesite.
fuente