472,145 Members | 1,391 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,145 software developers and data experts.

PL/PGSQL help for getting number of rows matched.


Hi,

We need to implement following logic efficiently.

SELECT * from some_table where .... [ Query 1 ]

IF rows_matched = 1 THEN

use the single row that matched.

ELSIF

loop thru the results of [Query 1]

END IF;
Currently i am doing select count(*) for getting rows_matched
in the top and repeating the same query in both branches of IF
to get the data of matching rows.

I have tried GET DIAGNOSTICS ROW_COUNT but for
"SELECTS" if returns 0 or 1 based on matching

I am sure there exists better methods. Kindly post a link
to better documentation of pl/pgsql or point out section in
the standard docs that discuss this issue.

Regds
Mallah.


---------------------------(end of broadcast)---------------------------
TIP 7: don't forget to increase your free space map settings

Nov 12 '05 #1
4 9047
Hello,

it isn't problem. You can write

SELECT INTO ....
IF FOUND THEN
...
END IF

or

SELECT INTO ..
GET DIAGNOSTICS variable = ROW_COUNT;
IF variable > 0 THEN
...
END IF

You can see on
http://developer.postgresql.org/docs...QL-SELECT-INTO

Regards
Pavel
On Mon, 10 Nov 2003, Rajesh Kumar Mallah wrote:

Hi,

We need to implement following logic efficiently.

SELECT * from some_table where .... [ Query 1 ]

IF rows_matched = 1 THEN

use the single row that matched.

ELSIF

loop thru the results of [Query 1]

END IF;
Currently i am doing select count(*) for getting rows_matched
in the top and repeating the same query in both branches of IF
to get the data of matching rows.

I have tried GET DIAGNOSTICS ROW_COUNT but for
"SELECTS" if returns 0 or 1 based on matching

I am sure there exists better methods. Kindly post a link
to better documentation of pl/pgsql or point out section in
the standard docs that discuss this issue.

Regds
Mallah.


---------------------------(end of broadcast)---------------------------
TIP 7: don't forget to increase your free space map settings

---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

http://archives.postgresql.org

Nov 12 '05 #2

On Mon, 10 Nov 2003, Pavel Stehule wrote:
Hello,

it isn't problem. You can write

SELECT INTO ....
IF FOUND THEN
...
END IF

or

SELECT INTO ..
GET DIAGNOSTICS variable = ROW_COUNT;
IF variable > 0 THEN
...
END IF

You can see on
http://developer.postgresql.org/docs...QL-SELECT-INTO
Probably sectino 37.7.4 of the docs ( in
http://developer.postgresql.org/docs...tructures.html
) is a better source as shown lower.

On Mon, 10 Nov 2003, Rajesh Kumar Mallah wrote:

Hi,

We need to implement following logic efficiently.

SELECT * from some_table where .... [ Query 1 ]

IF rows_matched = 1 THEN

use the single row that matched.

ELSIF

loop thru the results of [Query 1]

END IF;
Currently i am doing select count(*) for getting rows_matched
in the top and repeating the same query in both branches of IF
to get the data of matching rows.

I have tried GET DIAGNOSTICS ROW_COUNT but for
"SELECTS" if returns 0 or 1 based on matching

I am sure there exists better methods. Kindly post a link
to better documentation of pl/pgsql or point out section in
the standard docs that discuss this issue.


DECLARE
tup RECORD;
BEGIN
FOR tup IN select * from mytable
LOOP
Do the required action
END LOOP;
END

Indeed, I'm not even sure how to loop through the results of the query using
the scheme you show above. What do you assign the results of the select to?
--
Nigel Andrews
---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

Nov 12 '05 #3
On Monday 10 Nov 2003 5:38 pm, Pavel Stehule wrote:
Hello,

it isn't problem. You can write

SELECT INTO ....
IF FOUND THEN
...
END IF
I have *different* logic for match=1
and for match > 1 , so FOUND is not a
solution as manual says.
There is a special variable named FOUND of type boolean.
FOUND starts out false within each PL/pgSQL function.
It is set by each of the following types of statements:

Section 19.5.5
http://www.postgresql.org/docs/7.3/s...tatements.html

or

SELECT INTO ..
GET DIAGNOSTICS variable = ROW_COUNT;
IF variable > 0 THEN
...
END IF

Even this does not solve my problem.
See my actual code and the output.

-- ***************** CODE *******************
CREATE OR REPLACE FUNCTION general.copy_accounts() returns integer AS
'
DECLARE
users_c CURSOR FOR SELECT userid FROM general.user_accounts where userid=46 ;
userid_v int;
i int;
matched int;
rec RECORD;
BEGIN
OPEN users_c;

i := 1;
LOOP
FETCH users_c INTO userid_v;
EXIT WHEN NOT FOUND ;

SELECT INTO rec profile_id from general.profile_master where userid=userid_v;
GET DIAGNOSTICS matched = ROW_COUNT;
RAISE INFO ''matched = % '' , matched;

SELECT INTO matched count(*) from general.profile_master where userid=userid_v;
RAISE INFO ''matched = % '' , matched;

EXIT;

END LOOP;
CLOSE users_c;
RETURN 1;
END
' LANGUAGE 'plpgsql';

-- ------ CODE ENDS
RESULTS BELOW:

tradein_clients=# SELECT copy_accounts();
INFO: matched = 1
INFO: matched = 3

Note that matched was 3 but in first place it did not come.

+---------------+
| copy_accounts |
+---------------+
| 1 |
+---------------+
(1 row)

Time: 386.76 ms
tradein_clients=#
Regds
Mallah.

You can see on
http://developer.postgresql.org/docs...nts.html#PLPGS
QL-SELECT-INTO

Regards
Pavel

On Mon, 10 Nov 2003, Rajesh Kumar Mallah wrote:
Hi,

We need to implement following logic efficiently.

SELECT * from some_table where .... [ Query 1 ]

IF rows_matched = 1 THEN

use the single row that matched.

ELSIF

loop thru the results of [Query 1]

END IF;
Currently i am doing select count(*) for getting rows_matched
in the top and repeating the same query in both branches of IF
to get the data of matching rows.

I have tried GET DIAGNOSTICS ROW_COUNT but for
"SELECTS" if returns 0 or 1 based on matching

I am sure there exists better methods. Kindly post a link
to better documentation of pl/pgsql or point out section in
the standard docs that discuss this issue.

Regds
Mallah.


---------------------------(end of broadcast)---------------------------
TIP 7: don't forget to increase your free space map settings

---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/docs/faqs/FAQ.html

Nov 12 '05 #4
On Monday 10 Nov 2003 6:05 pm, Nigel J. Andrews wrote:
DECLARE
tup RECORD;
BEGIN
FOR tup IN select * from mytable
LOOP
Do the required action
END LOOP;
END
Indeed, I'm not even sure how to loop through the results of the query
using the scheme you show above. What do you assign the results of the
select to?

My working code which i think can be improved is below
note that i treat match=1 and match>1 differently.

I hope it will answer both of your question.

Thanks everyone for the responses though :)

Pl/Pgsql itself seems to be the most mature of all PL
hence we have decided to shift our business logic from
perl layer to DataBase for obvious gains.

-- Actual Code-------

CREATE OR REPLACE FUNCTION general.copy_accounts() returns integer AS

'

DECLARE

users_c CURSOR FOR SELECT userid FROM general.user_accounts ;
userid_v int;
i int;
matched int;
rec RECORD;

BEGIN

OPEN users_c;

i := 1;

LOOP
FETCH users_c INTO userid_v;
EXIT WHEN NOT FOUND ;
SELECT INTO matched count(*) from general.profile_master where userid=userid_v;
IF matched = 1 THEN
SELECT INTO rec email,title1 , fname1 , mname1 , lname1 , desg1 , mobile from general.profile_master where userid=userid_v;

ELSIF matched > 1 THEN

-- multiple profiles then get the profile that
-- has highest score.

SELECT INTO rec email,title1 , fname1 , mname1 , lname1 , desg1 , mobile,source
from general.profile_master join
general.temp_source_priority using(source) where userid=userid_v
order by profile_score(email,title1 , fname1 , mname1 , lname1 , desg1 , mobile) desc limit 1;

END IF;

IF matched >= 1 THEN
i := i + 1;
UPDATE general.user_accounts set
email= rec.email,
title= rec.title1 ,
fname= rec.fname1 ,
mname= rec.mname1 ,
lname= rec.lname1 ,
desg = rec.desg1 ,
mobile= rec.mobile where userid = userid_v;
END IF;

IF i % 100 = 0 THEN
RAISE INFO '' copied % accounts '' , i;
END IF;
END LOOP;

CLOSE users_c;
RAISE INFO '' Successfully finished with % accounts '' , i;

RETURN 1;

END

' LANGUAGE 'plpgsql';
---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to ma*******@postgresql.org so that your
message can get through to the mailing list cleanly

Nov 12 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Xizor | last post: by
reply views Thread by t_pet422 | last post: by
1 post views Thread by Jenny Zhang | last post: by
7 posts views Thread by Jim Crate | last post: by
2 posts views Thread by Tim Vadnais | last post: by
7 posts views Thread by harijay | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.