¿Cómo ejecutar función con parámetro en PostgreSQL utilizando bloqueo de código anónimo en FireDAC?
Mi base de datos (PostgreSQL 11) tiene una función que debe ser llamada a ejecutar una acción. El regreso no es importante, siempre y cuando no haya error. Esta función tiene argumentos que deben pasarse como parámetros.
No puedo utilizarlo directamente TFDConnection.ExecSQL
porque uso parámetros de tipo array que no es compatible con el método (a mi conocimiento). Así que, yo uso TFDQuery.ExecSQL
así:
msql1: = 'DO $$ BEGIN PERFORM DoIt (:id,:items); END $$; ';
{... create FDQuery (fq), set connection, set SQL.Text to msql1}
fq.Params.ParamByName ('id'). AsInteger: = 1;
{$ REGION 'items'}
fq.ParamByName ('items'). DataType: = ftArray;
fq.ParamByName ('items'). ArrayType: = atTable; // Must be atTable, not atArray
if length (items)> 0 then
begin
fq.ParamByName ('items'). ArraySize: = length (items);
for it: = 0 to length (items) -1 do
fq.ParamByName ('items'). AsIntegers [it]: = items [it];
end;
fq.ExecSQL;
{$ ENDREGION}
Al ejecutar el código anterior, el error anterior aumenta
"Parameter 'id' no encontrado".
Después de una investigación que sugirió usar fq.Params.ParamByName
También fui infructuosa.
Sin embargo, si cambia la forma en que se llama a la función
select DoIt (:id,:items);
y obviamente reemplazando la ejecución por fq.Open
funciona perfectamente.
¿Es posible ejecutar un bloque PL / pgSQL que contiene parámetros en la función llamada por este bloque utilizando TFDConnection / TFDQuery?
PS: Estoy usando Delphi Rio 10.3.3
Pregunta hecha hace 3 años, 5 meses, 5 días - Por techtrailblazer
3 Respuestas:
-
Cuando asignas un valor a
TFDQuery.
SQL, FireDAC hace algún preprocesamiento del SQL basado en varias opciones.ResourceOptions.CreateParams
Opción controla si los parámetros deben ser procesados. Esto está habilitado por defecto.El preprocesador reconoce literales de cadena en su SQL y no trata de buscar los parámetros en ellos. Tú usaste. dólar cotizado cadena constante y por eso FireDAC no reconoce los parámetros. Incluso si agregas un parámetro manualmente creo que FireDAC no ataría el valor.
Con eso dicho, la manera adecuada de ejecutar procedimientos/función almacenados es utilizar
TFDStoredProc
. Acabas de asignarStoredProcName
y llamar aPrepare
método que recuperará los metadatos del procedimiento (parameters) de la base de datos para que no necesite establecerArrayType
oDataType
del parámetro.En su código usted establece el
DataType
aftArray
lo que es incorrecto, porque en caso de parámetro array debe establecerse para el tipo de elemento de array. De todos modos, estableciendofq.ParamByName ('items').AsIntegers
Usted efectivamente establece el parámetroDataType
aftInteger
. Todo lo que necesitas hacer es establecerArraySize
Esto es lo que deberías hacer en su lugar:
procedure DoIt(Connection: TFDConnection; ID: Integer; const Items: TArray
); var StoredProc: TFDStoredProc; ParamItems: TFDParam; Index: Integer; begin StoredProc := TFDStoredProc.Create(nil); try StoredProc.Connection := Connection; StoredProc.StoredProcName := 'DoIt'; StoredProc.Prepare; StoredProc.Params.ParamByName('id').AsInteger := ID; if Length(Items) > 0 then begin ParamItems := StoredProc.Params.ParamByName('items'); ParamItems.ArraySize := Length(Items); for Index := Low(Items) to High(Items) do ParamItems.AsIntegers[Index] := Items[Index]; end; StoredProc.ExecProc; finally StoredProc.Free; end; end; Alternativamente puede utilizar
ExecFunc
para obtener el resultado de la función almacenada.Respondida el Dec 17, 2020 a las 19:17 - por pixelprodigy
Votos positivos: 0 | Votos negativos: 0 -
Para ejecutar una función con parámetro en PostgreSQL utilizando bloqueo de código anónimo en FireDAC, puedes intentar lo siguiente:
En lugar de utilizar
fq.Params.ParamByName
para establecer los parámetros, intenta asignar directamente los valores a través deTFDQuery.Params
de la siguiente manera:delphi msql1 := 'DO $$ BEGIN PERFORM DoIt(:id,:items); END $$;'; {... create FDQuery (fq), set connection, set SQL.Text to msql1} fq.Params[0].AsInteger := 1; // Establecer el parámetro id {$REGION 'items'} fq.Params[1].DataType := ftArray; fq.Params[1].ArrayType := atTable; // Debe ser atTable, no atArray if Length(items) > 0 then begin fq.Params[1].ArraySize := Length(items); for it := 0 to Length(items) - 1 do fq.Params[1].AsIntegers[it] := items[it]; end; fq.ExecSQL; {$ENDREGION}
En este código, he reemplazado
fq.ParamByName
confq.Params[]
, donde el índice0
corresponde al parámetroid
y el índice1
corresponde al parámetroitems
.Espero que esta solución te ayude a resolver el error "Parameter 'id' not found" al ejecutar la función con parámetros en PostgreSQL utilizando FireDAC en Delphi. ¡Déjame saber si tienes alguna otra pregunta o si necesitas más ayuda!
Respondida el Dec 18, 2020 a las 19:14 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Solución:
El problema es que FireDAC no admite directamente la asignación de nombres de parámetros a bloques de código PL/pgSQL. Sin embargo, hay una solución alternativa que puedes utilizar:
- Crea un procedimiento almacenado que llame a la función con parámetros nombrados.
- Utiliza `TFDConnection.ExecProc` para ejecutar el procedimiento almacenado, pasando los parámetros necesarios.
Ejemplo:
Procedimiento almacenado:
sql CREATE OR REPLACE PROCEDURE DoItWithParams(id integer, items integer[]) AS $$ BEGIN PERFORM DoIt(id, items); END; $$ LANGUAGE plpgsql;
Código FireDAC:
delphi // Crea un FDConnection y establece la conexión a la base de datos msql1 := 'CALL DoItWithParams(:id, :items);'; {... Crea FDQuery (fq), establece la conexión y establece SQL.Text en msql1} fq.Params.ParamByName('id').AsInteger := 1; {$ REGION 'items'} fq.ParamByName('items').DataType := ftArray; fq.ParamByName('items').ArrayType := atTable; if length(items) > 0 then begin fq.ParamByName('items').ArraySize := length(items); for it := 0 to length(items) - 1 do fq.ParamByName('items').AsIntegers[it] := items[it]; end; fq.ExecProc; {$ ENDREGION}
Beneficios:
Esta solución proporciona un enfoque más limpio y estructurado para ejecutar funciones con parámetros en PostgreSQL utilizando FireDAC. Permite utilizar nombres de parámetros, lo que mejora la legibilidad y el mantenimiento del código. * Aprovecha las funciones nativas de PostgreSQL, lo que puede mejorar el rendimiento en algunos casos.
Respondida el Dec 18, 2020 a las 19:19 - por Gemini
Votos positivos: 0 | Votos negativos: 0