SQL y Delphi, problemas con imágenes
2 Respuestas
Hay un tipo de datos llamado image pensado para eso, aunque el tratamiento es un poco complicado. Te pego un trozo de la ayuda que seguro que lo explica mejor que yo:
Administrar datos ntext, text e image
Los tipos de datos ntext, text e image de Microsoft® SQL ServerT pueden contener cantidades extremadamente grandes de datos (hasta 2 GB) en un único valor. Normalmente, un valor individual de este tipo de datos es mayor de lo que una aplicación puede recuperar en un paso, ya que algunos valores pueden ser incluso mayores que la memoria virtual disponible en el cliente. Esto significa que, para recuperarlos, normalmente se necesita llevar a cabo procedimientos especiales.
Si un dato de tipo ntext, text e image no es mayor que una cadena Unicode, de caracteres o binaria (4.000 caracteres, 8.000 caracteres y 8.000 bytes, respectivamente), se puede hacer referencia a su valor en las instrucciones SELECT, UPDATE e INSERT casi de la misma forma que se utiliza con los tipos de datos más pequeños. Por ejemplo, se puede hacer referencia a una columna ntext con un valor pequeño en una lista de selección de una instrucción SELECT de la misma forma que se hace referencia a una columna nvarchar. Se deben tener en cuenta algunas restricciones, como, por ejemplo, no poder hacer referencia directamente a una columna ntext, text o image en una cláusula WHERE. Estas columnas se pueden incluir en una cláusula WHERE como parámetros de una función que devuelve otro tipo de datos (como ISNULL, SUBSTRING o PATINDEX) o se encuentra en una expresión IS NULL, IS NOT NULL o LIKE.
Controlar valores de datos mayores
Sin embargo, cuando los valores de datos ntext, text e image son mayores, deben tratarse de bloque en bloque. Tanto Transact-SQL como las API de bases de datos contienen funciones que permiten a las aplicaciones funcionar con los datos ntext, text e image bloque a bloque.
Las API de bases de datos siguen un patrón común en cuanto a la forma en la que tratan las columnas grandes de tipo ntext, text e image.
Para leer una columna con datos de gran tamaño, la aplicación simplemente incluye la columna ntext, text o image en una lista de selección y, a continuación, vincula la columna a una variable de programa que sea suficientemente grande para contener un bloque razonable de los datos. La aplicación ejecuta entonces la instrucción y usa una función o método de la API para recuperar los datos en la variable vinculada, de bloque en bloque.
Para escribir una columna grande, la aplicación ejecuta una instrucción INSERT o UPDATE con un marcador de parámetro (?) En el lugar del valor que se va a colocar en la columna ntext, text o image. El marcador de parámetro (o parámetro, en el caso de ADO) se vincula a una variable de programa suficientemente grande para contener los bloques de datos. La aplicación entra en un bucle donde primero mueve el siguiente conjunto de datos a la variable vinculada y luego llama a una función o método de la API para escribir ese bloque de datos. Esto se repite hasta que se hayan enviado todos los datos.
Utilizar 'text in row'
En Microsoft SQL Server 2000, los usuarios pueden habilitar una opción text in row sobre una tabla, para que pueda almacenar datos de tipo text, ntext o image en su fila de datos.
Para habilitar la opción, ejecute el procedimiento almacenado sp_tableoption y especifique text in row como nombre de la opción y on como valor de la acción. El tamaño máximo predeterminado que se puede almacenar en una fila para un BLOB (objeto binario grande: datos text, ntext o image) es de 256 bytes, pero los valores pueden ir de 24 a 7000. Para especificar un tamaño máximo distinto del predeterminado, especifique un número entero dentro del intervalo de valores de la opción.
Las cadenas text, ntext e image se almacenan en la fila de datos si se cumplen las siguientes condiciones:
La opción text in row está habilitada.
La longitud de la cadena es menor que el límite especificado en @OptionValue.
Hay suficiente espacio disponible en la fila de datos.
Cuando se almacenan cadenas BLOB en la fila de datos, la lectura o escritura de cadenas text, ntext o image puede ser tan rápida como la lectura o escritura de cadenas de caracteres y binarias. SQL Server no tiene acceso a páginas separadas para leer o escribir la cadena BLOB.
Si una cadena text, ntext o image es mayor que el límite especificado o que el espacio que hay disponible en la fila, lo que se almacena en la fila son punteros. Las condiciones para almacenar las cadenas BLOB en la fila siguen siendo válidas aunque: debe haber espacio suficiente para almacenar los punteros en la fila de datos.
Para obtener más información, consulte sp_tableoption.
Utilizar punteros de texto
A menos que se especifique la opción text in row, las cadenas text, ntext e image se almacenan de forma externa a la fila de datos; en las filas de datos sólo residen los punteros para estas cadenas. Los punteros de texto apuntan al nodo raíz de un árbol compuesto de punteros internos, que apuntan a las páginas en las que se almacenan realmente los fragmentos de cadena (de datos text, ntext e image).
Los punteros de texto de fila de SQL Server 2000 son diferentes de los punteros de texto de versiones anteriores de SQL Server. Los punteros de texto de fila se comportan como controladores de archivos para los datos BLOB; los punteros de texto anteriores funcionan como direcciones a los datos BLOB. En consecuencia, cuando utilice punteros de texto de fila deberá tener en cuenta las siguientes características:
Importante Aunque en un cursor se permite texto de fila, no se permite un puntero de texto de fila. SQL Server devolverá un mensaje de error (8654, 16, 1, 'No se pudo generar un plan de cursor para la instrucción dada, porque contiene textptr(inrow lob). ', 1033) si intenta declarar un cursor que contenga un puntero de texto de fila.
Número
Se permite un máximo de 1024 punteros de texto de fila activos por transacción y por base de datos.
Bloqueo
Cuando un usuario obtiene un puntero de texto activo, SQL Server 2000 bloquea la fila de datos y garantiza que ningún otro usuario modifique o elimine la fila mientras el primer usuario tiene el puntero de texto. El bloqueo se libera cuando el puntero de texto deja de ser válido. Para invalidar un puntero de texto, utilice sp_invalidate_textptr.
No se puede utilizar un puntero de texto para actualizar valores BLOB cuando el nivel de aislamiento de la transacción es de lectura no confirmada o cuando la base de datos está en modo de sólo lectura.
SQL Server 2000 no bloquea la fila de datos si la base de datos está en modo de usuario único.
Como ejemplo, dada la tabla siguiente:
CREATE TABLE t1 (c1 int, c2 text)
EXEC sp_tableoption 't1', 'text in row', 'on'
INSERT t1 VALUES ('1', 'a')
La transacción siguiente se completará correctamente:
INSERT t1 VALUES ('1','This is text.')
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
GO
BEGIN TRAN
DECLARE @ptr varbinary(16)
SELECT @ptr = textptr(c2)
FROM t1
WHERE c1 = 1
READTEXT t1.c2 @ptr 0 5
COMMIT TRAN
GO
La transacción siguiente producirá un error:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
GO
BEGIN TRAN
DECLARE @ptr varbinary(16)
SELECT @ptr = textptr(c2)
FROM t1
WHERE c1 = 1
WRITETEXT t1.c2 @ptr 'xx'
COMMIT TRAN
GO
Duración (segundos)
Los punteros de texto de fila sólo son válidos en una transacción. Cuando una transacción se confirma, el puntero de texto deja de ser válido.
Dentro de una transacción, los punteros de texto de fila pueden dejar de ser válidos cuando tienen lugar las acciones siguientes:
La sesión termina.
La fila de datos se elimina en la misma transacción. (Otras transacciones no pueden eliminar una fila de datos debido al bloqueo que se obtiene sobre ella.)
Se cambia el esquema de la tabla en la que reside el puntero de texto. Entre las acciones de cambio de esquema que invalidan los punteros de texto se incluyen: crear o quitar un índice agrupado, alterar o quitar la tabla, truncar la tabla, cambiar la opción text in row mediante sp_tableoption y ejecutar sp_indexoption.
Utilizando el ejemplo anterior, la secuencia de comandos siguiente funcionaría en versiones anteriores de SQL Server, pero generará un error en SQL Server 2000.
DECLARE @ptrval varbinary(16)
PRINT 'get error here'
SELECT @ptrval = TEXTPTR(c2)
FROM t1
WHERE c1 = 1
READTEXT t1. C2 @ptrval 0 1
En SQL Server 2000, el puntero de texto de fila debe utilizarse dentro de una transacción:
Begin tran
DECLARE @ptrval varbinary(16)
SELECT @ptrval = TEXTPTR(c2)
FROM t1
WHERE c1 = 1
READTEXT t1.c2 @ptrval 0 1
COMMIT
Texto NULL
Puede obtener un puntero de texto de fila para texto NULL generado por INSERT. Anteriormente, sólo era posible obtener punteros de texto después de actualizar de BLOB a NULL.
Por ejemplo, el código siguiente no funciona en SQL Server 7.0, pero sí en SQL Server 2000.
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
GO
INSERT INTO t1 VALUES (4, NULL)
BEGIN TRAN
DECLARE @ptrval VARBINARY(16)
SELECT @ptrval = TEXTPTR(c2)
FROM t1
WHERE c1 = 4
WRITETEXT t1.c2 @ptrval 'x4'
COMMIT
En SQL Server 7.0 debe hacerse lo siguiente:
INSERT INTO t1 VALUES (4, NULL)
UPDATE t1
SET c2 = NULL
WHERE c1 = 4
DECLARE @ptrval VARBINARY(16)
SELECT @ptrval = TEXTPTR(c2)
FROM t1
WHERE c1 = 4
WRITETEXT t1.c2 @ptrval 'x4'
Esta tabla resume las diferencias.
Diferencia Puntero de texto en fila Puntero no de texto en fila
Número Máximo de 1024 activos por transacción y por base de datos. Sin límite.
Bloqueo La fila de datos tiene un bloqueo tipo ES hasta que el puntero deja de ser válido.
No se obtienen bloqueos cuando el estado de la transacción es 'lectura no confirmada' o la base de datos se encuentra en modo de 'usuario único' o 'sólo lectura'.
La fila de datos no se bloquea.
Duración (segundos) Deja de ser válido al final de la transacción o sesión, cuando se elimina una fila o cuando se cambia el esquema de la tabla. Deja de ser válido cuando se elimina la fila.
Texto NULL Puede obtenerse inmediatamente después de insertar el texto NULL. Sólo puede obtenerse después de actualizar.
Utilizar datos ntext, text e image con las API de bases de datos
A continuación se muestra un resumen de la forma en que las API de bases de datos tratan los datos ntext, text e image:
ADO
ADO puede asignar columnas o parámetros ntext, text o image a un objeto Field o Parameter. Use el método GetChunk para recuperar los datos de bloque en bloque, y el método AppendChunk para escribir datos de bloque en bloque. Para obtener más información, consulte Managing Long Data Types.
Ole db
OLE DB usa la interfaz ISequentialStream para admitir los tipos de datos ntext, text e image. El método ISequentialStream::Read lee los datos de gran tamaño de bloque en bloque e ISequentialStream::Write los escribe en la base de datos del mismo modo. Para obtener más información, consulte BLOBs and OLE Objects.
ODBC
ODBC tiene una característica llamada "datos en ejecución" para tratar los tipos de datos ODBC que contienen datos de gran tamaño: SQL_WLONGVARCHAR (ntext), SQL_LONGVARCHAR (text) y SQL_LONGVARBINARY (image). Estos tipos de datos se vinculan a una variable de programa. A continuación, se llama a SQLGetData para recuperar los datos grandes de bloque en bloque y a SQLPutData para enviar los datos grandes de bloque en bloque. Para obtener más información, consulte Managing text and image Columns.
DB-Library
Las aplicaciones de DB-Library también vinculan columnas ntext, text e image a variables de programa. La función dbtxtptr de DB-Library se usa para obtener un puntero a la ubicación de la columna de gran tamaño en la base de datos. Dbreadtext se usa para leer los datos grandes de bloque en bloque. Las funciones como dbwritetext, dbupdatetext y dbmoretext se usan para escribir los datos grandes de bloque en bloque.
- Compartir respuesta
Para insertar imágenes en una base de datos SQL desde Delphi 6, generalmente se sigue un enfoque que implica convertir la imagen a un formato binario (como un blob) y luego insertarlo en la base de datos. Aquí te doy un ejemplo básico de cómo podrías hacerlo:
Preparación en SQL: Asegúrate de tener una tabla que contenga un campo de tipo BLOB o similar donde puedas almacenar la imagen.
En Delphi 6: Utiliza componentes adecuados para manipular bases de datos y trabajar con imágenes.
- Asegúrate de tener configurada la conexión a tu base de datos SQL desde Delphi utilizando componentes como TDatabase, TQuery, TTable, o componentes similares según tu preferencia y el acceso a datos que estés utilizando (como BDE o ADO).
Insertar una imagen: procedure InsertarImagen(const NombreImagen: string; const Imagen: TGraphic);
var
Query: TQuery;
Stream: TMemoryStream;
begin
Query := TQuery.Create(nil);
try
Query.DatabaseName := 'NombreDeTuConexion'; // Nombre de tu conexión a la base de datos
Query.SQL.Text := 'INSERT INTO Imagenes (Nombre, Foto) VALUES (:Nombre, :Foto)';
Query.ParamByName('Nombre').AsString := NombreImagen;
// Convertir la imagen a un stream de memoria
Stream := TMemoryStream.Create;
try
Imagen.SaveToStream(Stream);
Stream.Position := 0;
Query.ParamByName('Foto').LoadFromStream(Stream, ftBlob);
finally
Stream.Free;
end;
Query.ExecSQL;
finally
Query.Free;
end;
end;Cómo llamar a la función:
// Ejemplo de cómo llamar a la función InsertarImagen
var
Imagen: TBitmap; // o cualquier otro tipo de TGraphic según el tipo de imagen que manejes
begin
Imagen := TBitmap.Create;
try
Imagen.LoadFromFile('ruta/a/tu/imagen.jpg'); // Cargar la imagen desde un archivo
InsertarImagen('NombreDeLaImagen', Imagen); // Insertar la imagen en la base de datos
finally
Imagen.Free;
end;
end;Este es un ejemplo básico y simplificado para mostrarte cómo puedes insertar imágenes en una base de datos SQL desde Delphi 6. Asegúrate de ajustar el código según tu estructura de base de datos y los componentes específicos que estés utilizando en Delphi para el acceso a datos.
- Compartir respuesta