Postgres function with dblink - postgresql

Got a problem here with following function in postgresql function:
im getting following error :
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function savegamelog(text,text,integer,integer,bigint,bigint,bigint,integer,integer,integer,integer) line 15 at SQL statement
my function is as follows:
DECLARE
s text;
pDatatime integer;
pDataid bigint;
BEGIN
pDatatime = floor(extract(epoch from '["now()",]'::timestamp));
IF length(pTableName) > 0 THEN
UPDATE lastgamedata SET data= pData::bytea, gameid= pGameid, balance= pBalance ,bet= pBet, win= pWin, betline= pBetline, lines=pLines, datatime= pDatatime WHERE uid= pUserid;
END IF;
UPDATE gamestatistic SET totalin =totalin+pBet , totalout =totalout+pWin WHERE gameindex=pGameid;
SELECT dblink_connect('host=127.0.0.1
user=user
password=pass
dbname=dbname');
SELECT dblink_exec('UPDATE hall SET totalbetin = totalbetin+pBet , totalbetout =totalbetout+pWin WHERE id = (SELECT roomnumber FROM users WHERE uid = pUserid)');
INSERT INTO gamedata( sessionID, uid, gameID, key, balance, bet, win, betline, lines, datatime, type, denomination ) VALUES ( 0, pUserid, pGameid, 0, pBalance, pBet, pWin, pBetline, pLines, pDatatime, pType, pDenomination ) RETURNING dataid INTO pDataid;
INSERT INTO gamedata_storage ( dataid, data ) VALUES ( pDataid, pData::bytea );
return pDataid;
END;
i know the function is wrong, and i dont know how to fix it..
can anybody point me in the correct direction pls..

following the error message instructions, change
SELECT dblink_connect('host=127.0.0.1
user=user
password=pass
dbname=dbname');
to
PERFORM dblink_connect('host=127.0.0.1
user=user
password=pass
dbname=dbname');

Related

Postgres functions how to return an array of multiple elements

I want to create a function to return an array of multiple elements, the query work perfect but I can't execute as function because I'm getting error always, this is my function:
CREATE OR REPLACE FUNCTION public.buscarexamen(visit anyelement)
RETURNS anyelement
LANGUAGE plpgsql
AS $function$
BEGIN
return array(SELECT fn_folio_paciente(vi.clave_unilabor, vi.fecha, vi.consec) AS folio_paciente,
vi.cve_visita, gp.nombre AS nombre_grupo, gp.cve_grupo,
--
vp.cve_visita_prueba, p.cve_prueba, p.nombre AS nombre_prueba, me.nombre AS nombre_metodo,
--
gcf.visible AS visible_grupo,
cf.cve_grupo_campo_formato, gc.nombre_grupo_campo AS grupo_parametro, cf.nombre AS nombre_parametro,
cf.orden, cf.tipo_dato, cf.solo_lectura AS tipo_titulo,
cf.cve_seccion_padre, cf.tiene_elementos_seccion, cf.observacion AS observacion_parametro,
--
pr.cve_prueba_resultado, pr.tipo_formato_prueba AS tipo_formato, pr.cantidad_resultado AS cantidad_parametro,
pr.observaciones AS observacion_analista, pr.observaciones_prueba,
CASE
WHEN (TRIM(pr.observaciones) <> '') OR (TRIM(pr.observaciones_prueba) <> '') THEN 1
ELSE 0 END AS prueba_tiene_observacion,
--
rc.cve_resultado_campo, rc.resultado, rc.observacion AS observacion_resultado, rc.signo, rc.decimales, cf.xleft as cursiva,
vr.valor_referencia_min, vr.valor_referencia_max, un.nombre AS nombre_unidad,
cf.tiene_valores_referencia
FROM visitas vi
JOIN corporativo.unilabor_unidades uu ON (vi.cve_unilabor_unidad = uu.cve_unilabor_unidad)
JOIN visita_pruebas vp ON (vi.cve_visita = vp.cve_visita)
JOIN prueba_resultados pr ON (vp.cve_visita_prueba = pr.cve_visita_prueba)
JOIN prueba_metodo pm ON (pr.cve_prueba_metodo = pm.cve_prueba_metodo)
JOIN metodos me ON (pm.cve_metodo = me.cve_metodo)
JOIN pruebas p ON (pr.cve_prueba = p.cve_prueba)
JOIN grupos gh ON (p.cve_grupo = gh.cve_grupo)
JOIN grupos gp ON (gh.cve_grupo_padre = gp.cve_grupo)
JOIN pacientes pa ON (vi.cve_paciente = pa.cve_paciente)
JOIN contratos co ON (vi.cve_contrato = co.cve_contrato AND co.contrato_cerrado = 0)
JOIN resultados_campos rc ON (pr.cve_prueba_resultado = rc.cve_prueba_resultado)
JOIN unidades un ON (rc.cve_unidad = un.cve_unidad)
LEFT JOIN valor_referencia_resultado vr ON (rc.cve_resultado_campo = vr.cve_resultado_campo)
JOIN campos_formatos cf ON (rc.cve_campo_formato = cf.cve_campo_formato)
JOIN grupos_campos_formato gcf ON (cf.cve_grupo_campo_formato = gcf.cve_grupo_campo_formato)
JOIN grupos_campos gc ON (gcf.cve_grupo_campo = gc.cve_grupo_campo)
WHERE vi.cve_visita = 696787
AND cf.solo_lectura = 0
ORDER BY p.orden_prueba, pr.cve_prueba_resultado, gcf.orden_grupo, rc.orden_local, vr.orden_valor);
END;
$function$
;
I try to use:
select * from buscarexamen(123123);
On SQL Script return this:
SQL Error [42601]: ERROR: subquery must return only one column Where: PL/pgSQL function buscarexamen(anyelement) line 3 at RETURN
Really I spend a lot of time finding solutions but until now isn't working.
Any help is really apreciated.
Regards.
Your objective sounds like strange. However you should be able to achieve it by creating a composite type your_composite_type :
CREATE TYPE your_composite_type AS
( folio_paciente folio_paciente_data_type
, cve_visita cve_visita_data_type
, nombre_grupo nombre_grupo_data_type
, cve_grupo cve_grupo_data_type
, cve_visita_prueba cve_visita_prueba_data_type
, cve_prueba cve_prueba_data_type
, nombre_prueba nombre_prueba_data_type
, nombre_metodo nombre_metodo_data_type
, visible_grupo visible_grupo_data_type
, [...]
, nombre_unidad nombre_unidad_data_type
, tiene_valores_referencia tiene_valores_referencia_data_type
) ;
Then the function public.buscarexamen() can return an array of data type your_composite_type :
CREATE OR REPLACE FUNCTION public.buscarexamen(visit anyelement)
RETURNS your_composite_type[] -- instead of anyarray
LANGUAGE plpgsql
AS $function$
BEGIN
return array(SELECT row( fn_folio_paciente(...)
, vi.cve_visita, gp.nombre, gp.cve_grupo
, [...]
, vr.valor_referencia_min, vr.valor_referencia_max, un.nombre
, cf.tiene_valores_referencia
) :: your_composite_type
FROM visitas vi
JOIN [...]
WHERE [...]
ORDER BY p.orden_prueba, pr.cve_prueba_resultado, gcf.orden_grupo, rc.orden_local, vr.orden_valor)
) ;
END;
$function$
;

ColdFusion 2016 and stored proc throwing invalid character error

I am trying existing code in a CF 2016 install... I get this error
"[Macromedia][DB2 JDBC Driver][DB2]ILLEGAL SYMBOL =; VALID SYMBOLS ARE ..."
the line identified is a param of a stored proc call that looks like this:
<cfstoredproc datasource="#application.dsn#" procedure="LIVE.STOPS">
<cfprocparam type="In" cfsqltype="CF_SQL_BIGINT" dbvarname="STOPID" value="#val( variables.procstopid )#" null="no">
<cfprocparam type="In" cfsqltype="CF_SQL_INTEGER" dbvarname="TRIPID" value="#val( url.tripId )#" null="no">
</cfstoredproc>
I cannot find any mention on line of a change in stored proc tag - maybe the DB2 driver? I'm looking for any input. Thanks.
Other info;
Windows10, Apache2.4, connectiong to DB2 v10.
#pendo, Here is the stored proc - it should be noted that I abbreviated some of the sql, but the SP works and has for a long time in the app running CF10.
CREATE OR REPLACE PROCEDURE LIVE.STOP(
IN stopId BIGINT DEFAULT 0,
IN tripId INTEGER DEFAULT 0
) LANGUAGE SQL
BEGIN
DECLARE updateTripId INTEGER DEFAULT 0;
DECLARE minStopId BIGINT DEFAULT 0;
DECLARE maxStopId BIGINT DEFAULT 0;
DECLARE TripSearch_cursor CURSOR FOR
SELECT s1.fkTripsId
FROM live.paymentsTripsStops s1
JOIN live.Trips t ON s1.fkTripsId = t.Id
WHERE s1.fkStopsId = stopId
FETCH FIRST 1 ROWS ONLY;
DECLARE minMaxStop_cursor CURSOR FOR
SELECT
COALESCE(
(
SELECT s.Id
FROM live.Stops s
JOIN live.Trips t ON s.fkTripsId = t.Id
ORDER BY s.Sequence
FETCH FIRST 1 ROWS ONLY
),
0
) AS firstStopId,
COALESCE(
(
SELECT s.Id
FROM live.Stops s
JOIN live.Trips t ON s.fkTripsId = t.Id
ORDER BY s.Sequence DESC
FETCH FIRST 1 ROWS ONLY
),
0
) AS lastStopId
FROM live.Trips t
WHERE t.Id = updateTripId
FETCH FIRST 1 ROWS ONLY;
IF TripId > 0
THEN SET updateTripId = TripId;
ELSE OPEN TripSearch_cursor;
FETCH FROM TripSearch_cursor INTO updateTripId;
CLOSE TripSearch_cursor;
END IF;
IF updateTripId > 0
THEN OPEN minMaxStop_cursor;
FETCH FROM minMaxStop_cursor INTO minStopId, maxStopId;
CLOSE minMaxStop_cursor;
UPDATE live.Trips
SET fkFirstStopId = minStopId,
fkLastStopId = maxStopId
WHERE intId = updateTripId;
END IF;
END

SQL Server : error "Must Declare the Scalar Variable"

Trying to insert into a table from other two tables with a loop
DECLARE #RowCount INT
SET #RowCount = (SELECT Max(FogTopicsID) FROM FSB_FogTopics )
DECLARE #I INT
SET #I = 1
WHILE (#I <= #RowCount)
BEGIN
DECLARE #FogID INT, #StudentID INT, #TopicID INT, #ProcessStudentId INT
SELECT #FogID = FogID, #StudentID = StudentID, #TopicID = TopicsID
FROM FSB_FogTopics
WHERE FogTopicsID = #I
SELECT #ProcessStudentId = ProStudentId
FROM FSB_ProcessStudents
WHERE ProcessId = #FogID AND StudentId = #StudentID
INSERT INTO FSB_ProcessTopics( [ProcessStudentId], [TopicId])
VALUES (#ProcessStudentId, #TopicID)
SET #I = #I + 1
END
but I get an error
Must Declare the Scalar Variable #ProcessStudentId
As pointed out by forklift's comment - You can use proper set based solution instead of horrible loop like so;
INSERT FSB_ProcessTopics( [ProcessStudentId], [TopicId])
SELECT
s.ProStudentId,
f.TopicsId
FROM FSB_FogTopics f
INNER JOIN FSB_ProcessStudents s
ON f.FogId = s.ProcessId
AND f.StudentId = s.StudentId
While I realise this doesn't answer your question per-say, this is a better way to do it and should eliminate the need to solve your problem...
You probably have non-continuous Ids - So you have 1,2,4 as Ids but your code is trying to dind 1,2,3,4
You don't need loops to do this (you should almost never need to use loops in SQL for anything). You can do your INSERT in a single statement:
Insert FSB_ProcessTopics
(ProcessStudentId, TopicId)
Select P.ProStudentId, T.TopicsId
From FSB_FogTopics T
Join FSB_ProcessStudents P On P.ProcessId = T.FogId
And P.StudentId = T.StudentId
Do this as a single statement:
INSERT FSB_ProcessTopics(ProcessStudentId, TopicId)
SELECT ProStudentId, TopicsID
FROM FSB_FogTopics ft JOIN
FSB_ProcessStudents ps
ON ft.StudentID = ps.StudentId AND sps.ProcessId = ft.FogiId;
This should replace the cursor, the loop, everything.

PostgreSQL ERROR: invalid input syntax for integer: "1e+06"

The full error message is:
ERROR: invalid input syntax for integer: "1e+06"
SQL state: 22P02
Context: In PL/R function sample
The query I'm using is:
WITH a as
(
SELECT a.tract_id_alias,
array_agg(a.pgid ORDER BY a.pgid) as pgids,
array_agg(a.sample_weight_geo ORDER BY a.pgid) as block_weights
FROM results_20161109.block_microdata_res_joined a
WHERE a.tract_id_alias in (66772, 66773, 66785, 66802, 66805, 66806, 66813)
AND a.bldg_count_res > 0
GROUP BY a.tract_id_alias
)
SELECT NULL::INTEGER agent_id,
a.tract_id_alias,
b.year,
unnest(shared.sample(a.pgids,
b.n_agents,
1 * b.year,
True,
a.block_weights)
) as pgid
FROM a
LEFT JOIN results_20161109.initial_agent_count_by_tract_res_11 b
ON a.tract_id_alias = b.tract_id_alias
ORDER BY b.year, a.tract_id_alias, pgid;
And the shared.sample function I'm using is:
CREATE OR REPLACE FUNCTION shared.sample(ids bigint[], size integer, seed integer DEFAULT 1, with_replacement boolean DEFAULT false, probabilities numeric[] DEFAULT NULL::numeric[])
RETURNS integer[] AS
$BODY$
set.seed(seed)
if (length(ids) == 1) {
s = rep(ids,size)
} else {
s = sample(ids,size, with_replacement,probabilities)
}
return(s)
$BODY$
LANGUAGE plr VOLATILE
COST 100;
ALTER FUNCTION shared.sample(bigint[], integer, integer, boolean, numeric[])
OWNER TO "server-superusers";
I'm pretty new to this stuff, so any help would be appreciated.
Not a problem of the function. Like the error messages says: The string '1e+06' cannot be cast to integer.
Obviously, the columns n_agents in your table results_20161109.initial_agent_count_by_tract_res_11 is not an integer column. Probably type text or varchar? (That info would help in your question.)
Either way, the assignment cast does not work for the target type integer. But it does for numeric:
Does not work:
SELECT '1e+06'::text::int; -- error as in question
Works:
SELECT '1e+06'::text::numeric::int;
If my assumptions hold, you can use this as stepping stone.
Replace b.n_agents in your query with b.n_agents::numeric::int.
It's your responsibility that numbers stay in integer range, or you get the next exception.
If that did not nail it, you need to look into function overloading:
Is there a way to disable function overloading in Postgres
And function type resolution:
PostgreSQL function call
The schema search path is relevant in many related cases, but you did schema-qualify all objects, so we can rule that out.
How does the search_path influence identifier resolution and the "current schema"
Your query generally looks good. I had a look and only found minor improvements:
SELECT NULL::int AS agent_id -- never omit the AS keyword for column alias
, a.tract_id_alias
, b.year
, s.pgid
FROM (
SELECT tract_id_alias
, array_agg(pgid) AS pgids
, array_agg(sample_weight_geo) AS block_weights
FROM ( -- use a subquery, cheaper than CTE
SELECT tract_id_alias
, pgid
, sample_weight_geo
FROM results_20161109.block_microdata_res_joined
WHERE tract_id_alias IN (66772, 66773, 66785, 66802, 66805, 66806, 66813)
AND bldg_count_res > 0
ORDER BY pgid -- sort once in a subquery. cheaper.
) sub
GROUP BY 1
) a
LEFT JOIN results_20161109.initial_agent_count_by_tract_res_11 b USING (tract_id_alias)
LEFT JOIN LATERAL
unnest(shared.sample(a.pgids
, b.n_agents
, b.year -- why "1 * b.year"?
, true
, a.block_weights)) s(pgid) ON true
ORDER BY b.year, a.tract_id_alias, s.pgid;

SQL Scalar function element not recognized in TSQL program

I have an input db2 table with two elements: loan_number, debt_to_income; this table's name is #Input_Table. I am trying to run a test the function by running a SQL program against this table. The problem is that the function's element is not being recognized in the SQL program for some reason, maybe I have been looking at to long? I need to validate that the output in the table will output in a order by the debt_to_income field.
Here is the function code:
ALTER FUNCTION [dbo].[FN_DTI_BANDS]
(
-- the parameters for the function here
#FN_DTI_Band decimal(4,3)
)
RETURNS varchar(16)
AS
BEGIN
declare #Return varchar(16)
select #Return =
Case
when #FN_DTI_Band is NULL then ' Missing'
WHEN #FN_DTI_Band = 00.00 then ' Missing'
When #FN_DTI_Band < = 0.31 then 'Invalid'
When #FN_DTI_Band between 0.31 and 0.34 then '31-34'
When #FN_DTI_Band between 0.34 and 0.38 then '34-38'
When #FN_DTI_Band >= 0.38 then '38+'
else null end
-- Return the result of the function
RETURN #Return
END
Here is the T-SQL test program:
SELECT loan_number,dbo.FN_DTI_BANDS(debt_to_income)as FN_DTI_Band
from #Input_table
SELECT COUNT(*), FN_DTI_Band
FROM #Input_table
GROUP BY FN_DTI_Band
ORDER BY FN_DTI_Band
Here is the error:
Msg 207, Level 16, State 1, Line 7
Invalid column name 'FN_DTI_Band'.
Msg 207, Level 16, State 1, Line 5
Invalid column name 'FN_DTI_Band'.
Can someone help me spot what I am overlooking? Thank you!
the table #input_table does not have a column called FN_DTI_Band.
Just the result of the first select statement has that column name.
You need to make the first select statement a sub query of the 2nd
Something like this:
SELECT COUNT(*), T.FN_DTI_Band
FROM
(
SELECT loan_number,dbo.FN_DTI_BANDS(debt_to_income) as FN_DTI_Band
from #Input_table
) T
GROUP BY T.FN_DTI_Band
ORDER BY T.FN_DTI_Band
Try prepending "dbo" onto the name of the function.
Select Count(*), dbo.FN_DTI_Band
From....