ROWTYPE in CURSOR postgresql - postgresql

i want to know if it is possible to get "Rowtype" for a cursor in postgresql (pl/pgsql).
..
my cursor has a select from multiple table and i don't know how to get the rowtype.
c_Data CURSOR FOR
select
dst_description
, cnt_number
, prd_name
, grt_code
, res_currency
, res_date
, prm_installmentdate
from tbl_xxx, tbl_yyy, tbl_aaa
where cnt_id = res_xxx
and prd_id = cnt_yyy
and dst_id = prd_aaa
and grt_id = res_xxx
and prm_id = res_aaa;
l_Data c_Data%rowtype;
please help

More like this way round.
declare
l_data record;
begin
select
INTO l_data --<<
dst_description
, cnt_number
, prd_name
, grt_code
, res_currency
, res_date
, prm_installmentdate
from tbl_xxx, tbl_yyy, tbl_aaa
where cnt_id = res_xxx
and prd_id = cnt_yyy
and dst_id = prd_aaa
and grt_id = res_xxx
and prm_id = res_aaa;
l_data will then be of the rowtype you need.

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$
;

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.

Is there any query to find table structure in Oracle_sqldeveloper

Hi i am new to oracle_sqldeveloper can you please give me the answer how to know the table structure and relationships of a database.
You can try
DESC <table_name>
Try this:
select table_name, column_name, data_type
from all_tab_columns
where table_name = <TABLE_NAME_HERE>
and owner = '<YOUR_USER_HERE_IN_CAPITAL_LETTERS>'
If you have comments on your table then to get columns' comments:
select tc.table_name, tc.column_name, tc.data_type, cc.comments
from all_col_comments cc, all_tab_columns tc
where tc.table_name = <TABLE_NAME_HERE>
and tc.owner = <OWNER_OF_TABLE_HERE>
and tc.table_name = cc.table_name
and tc.column_name = cc.column_name
and tc.owner = cc.owner
If you are logged in under owner of the table you can write this:
select table_name, column_name, data_type
from user_tab_columns
where table_name = <TABLE_NAME_HERE>
or to get columns with comments
select tc.table_name, tc.column_name, tc.data_type, cc.comments
from user_col_comments cc, user_tab_columns tc
where tc.table_name = '<TABLE_NAME_HERE>'
and tc.owner = '<YOUR_USER_HERE_IN_CAPITAL_LETTERS>'
and tc.table_name = cc.table_name
and tc.column_name = cc.column_name
To get relationships between tables user this query:
select uc1.table_name
, uc1.constraint_name
, cc1.column_name
, uc2.table_name r_table_name
, uc2.constraint_name r_constraint_name
, cc2.column_name r_column_name
from all_constraints uc1
, all_constraints uc2
, all_cons_columns cc1
, all_cons_columns cc2
where 1 = 1
and uc2.constraint_type = 'R'
and uc1.constraint_name = uc2.r_constraint_name
and cc1.table_name = uc1.table_name
and cc1.constraint_name = uc1.constraint_name
and cc2.table_name = uc1.table_name
and cc2.constraint_name = uc1.constraint_name
and uc1.owner = '<YOUR_USER_HERE_IN_CAPITAL_LETTERS>'
and uc2.owner = uc1.owner
and cc1.owner = uc1.owner
and cc2.owner = uc1.owner
order by 1
/
Columns with the "R_" prefix mean that they are foreign data (they represent foreign keys). As you can see, I used the tables with the "ALL_" prefix, to use similar tables with the "USER_" prefix, get rid of the "OWNER" section.
To know more about oracle data dictionary read this
1) type your table name.
2) right click on table name & click Open Declaration.

Not permitted when the subquery has expression more than 1 value! in SQL Server 2008

First of all sorry for my english,
I'm trying to insert a record into a table ... the record is the difference between the project table and temp table ...
The code I came into is
insert into pro_updatelog
select *, #user_n, GETDATE()
from pro
where cod = (select cod
from (SELECT * FROM pro
EXCEPT
SELECT * FROM temp
UNION ALL
SELECT * FROM temp
EXCEPT
SELECT * FROM pro) as T1);
then merge the temp table and original table ...
Not sure what should I do ...
All I want is that if there is any differences between the original table and temp table get recorded the original values into pro_updatelog table ... it would be best if only updated value will be recorded in table but it doesn't matter if a full row will be recorded but I want the original values before the update recorded!
Any ideas would be much appreciated!
thanks
I have succeeded that by using merge ... how ever it will take much longer to complete the stored procedure but it will do as I want ->
insert into pro_updatelog
select * , #user_n, GETDATE() from
(SELECT * FROM pro
EXCEPT
SELECT * FROM temp
UNION ALL
SELECT * FROM temp
EXCEPT
SELECT * FROM pro) as T1;
merge pro_updatelog as tar
using pro as sor
on (tar.cod = sor.cod)
when matched then
update set
tar.cod = sor.cod ,
tar.name_pr = sor.name_pr ,
tar.name_pe = sor.name_pe ,
tar.en = sor.en ,
tar.ending = sor.ending ,
tar.b = sor.b ,
tar.date_p = sor.date_p ,
tar.nek = sor.nek ,
tar.date_kh = sor.date_kh ,
tar.mp = sor.mp ,
tar.mt = sor.mt ,
tar.no_p = sor.no_p ,
tar.mas = sor.mas ,
tar.mablag = sor.mablag ,
tar.np = sor.np ,
tar.nf = sor.nf ,
tar.nn = sor.nn ,
tar.hpp1 = sor.hpp1 ,
tar.hpp2 = sor.hpp2 ,
tar.hpp3 = sor.hpp3 ,
tar.hpp4 = sor.hpp4 ,
tar.hpp5 = sor.hpp5 ,
tar.hpp6 = sor.hpp6 ,
tar.hpp7 = sor.hpp7 ,
tar.hpp8 = sor.hpp8 ,
tar.hpf1 = sor.hpf1 ,
tar.hpf2 = sor.hpf2 ,
tar.hpf3 = sor.hpf3 ,
tar.hpf4 = sor.hpf4 ,
tar.hpf5 = sor.hpf5 ,
tar.hpf6 = sor.hpf6 ,
tar.hpf7 = sor.hpf7 ,
tar.hpf8 = sor.hpf8 ,
tar.mola = sor.mola ,
tar.name1 = sor.name1 ,
tar.name2 = sor.name2 ,
tar.name3 = sor.name3 ,
tar.name4 = sor.name4 ,
tar.name5 = sor.name5 ,
tar.name6 = sor.name6 ,
tar.mab_t = sor.mab_t ,
tar.zarib1 = sor.zarib1 ,
tar.zarib2 = sor.zarib2 ,
tar.zarib3 = sor.zarib3 ,
tar.zarib4 = sor.zarib4 ,
tar.datet1 = sor.datet1 ,
tar.datet2 = sor.datet2 ,
tar.grup = sor.grup ,
tar.mablag1 = sor.mablag1 ,
tar.cod_g = sor.cod_g ,
tar.cod_m = sor.cod_m ,
tar.user_n = #user_n ,
tar.[date]=getdate();

Does Not Exist using Multiple Columns

I am trying to find all records in my #TempTable that are not in the staging table.
Its important to note that the comparison needs to take place over 16 fields.
I have tried several combinations and nothing seems to work.
SELECT CustomerAccountNo FROM #TempTable
WHERE NOT EXISTS
(SELECT e.[CustomerAccountNo] ,
e.[MeterNo] ,
e.[CustomerName1] ,
e.[ServiceAddress1] ,
e.[ServiceAddress2] ,
e.[ServiceCity] ,
e.[ServiceState] ,
e.[ServiceZip] ,
e.[BillingAddress1] ,
e.[BillingAddress2] ,
e.[BillingAddress3] ,
e.[BillingCity] ,
e.[BillingState] ,
e.[BillingZip] ,
e.[BillingZip4] ,
e.[PrimaryPhoneNumber] FROM #TempTable e
JOIN dbo.Staging s
ON e.CustomerAccountNo = s.CustomerAccountNo AND
e.MeterNo = s.MeterNo AND
e.CustomerName1 = s.CustomerName1 AND
e.ServiceAddress1 = s.ServiceAddress1 AND
e.ServiceAddress2 = s.ServiceAddress2 AND
e.ServiceCity = s.ServiceCity AND
e.ServiceState = s.ServiceState AND
e.ServiceZip = s.ServiceZip AND
e.BillingAddress1 = s.BillingAddress1 AND
e.BillingAddress2 = s.BillingAddress2 AND
e.BillingAddress3 = s.BillingAddress3 AND
e.BillingCity = s.BillingCity AND
e.BillingState = s.BillingState AND
e.BillingZip = s.BillingZip AND
e.BillingZip4 = s.BillingZip4 AND
e.PrimaryPhoneNumber= s.PrimaryPhoneNumber
)
Instead of a JOIN, try using Except.
SELECT CustomerAccountNo, MeterNo -- and so on
FROM #TempTable
EXCEPT
SELECT CustomerAccountNo, MeterNo -- and so on
FROM Staging
Just do a join and look for null. Like this
SELECT e.*
FROM #TempTable e
LEFT JOIN dbo.Staging s
ON e.CustomerAccountNo = s.CustomerAccountNo AND
e.MeterNo = s.MeterNo AND
e.CustomerName1 = s.CustomerName1 AND
e.ServiceAddress1 = s.ServiceAddress1 AND
e.ServiceAddress2 = s.ServiceAddress2 AND
e.ServiceCity = s.ServiceCity AND
e.ServiceState = s.ServiceState AND
e.ServiceZip = s.ServiceZip AND
e.BillingAddress1 = s.BillingAddress1 AND
e.BillingAddress2 = s.BillingAddress2 AND
e.BillingAddress3 = s.BillingAddress3 AND
e.BillingCity = s.BillingCity AND
e.BillingState = s.BillingState AND
e.BillingZip = s.BillingZip AND
e.BillingZip4 = s.BillingZip4 AND
e.PrimaryPhoneNumber= s.PrimaryPhoneNumb
WHERE s.CustomerAccountNo is null
You should provide more detailed circumstance to get correct answer.
Clearly, you don't have any connection between your FROM clause and WHERE clause so the query will return all.
Try this one:
SELECT CustomerAccountNo FROM #TempTable t
WHERE NOT EXISTS
(SELECT 1 FROM dbo.Staging s WHERE
t.CustomerAccountNo = s.CustomerAccountNo AND
t.MeterNo = s.MeterNo AND
t.CustomerName1 = s.CustomerName1 AND
t.ServiceAddress1 = s.ServiceAddress1 AND
t.ServiceAddress2 = s.ServiceAddress2 AND
t.ServiceCity = s.ServiceCity AND
t.ServiceState = s.ServiceState AND
t.ServiceZip = s.ServiceZip AND
t.BillingAddress1 = s.BillingAddress1 AND
t.BillingAddress2 = s.BillingAddress2 AND
t.BillingAddress3 = s.BillingAddress3 AND
t.BillingCity = s.BillingCity AND
t.BillingState = s.BillingState AND
t.BillingZip = s.BillingZip AND
t.BillingZip4 = s.BillingZip4 AND
t.PrimaryPhoneNumber= s.PrimaryPhoneNumber
)