[SQL] Cursors and recursion

2005-12-28 Thread Don Croata
Hi,
 
I've been trying to do recursion and cursors in PL/PgSQL (PostgreSQL 8.1). It's a function who has a cursor and calls itself, but the problem raises after the first recursion, when PgSQL complains:
 
ERROR:  cursor "cur" already in use
 
Are the cursors kept globally? or cached like TEMP TABLE?
 
There's an example code available in http://www.croata.cl/cur.sql . In fact, it is an abstraction of the real stored procedure where the problem occurs.
 
--
 
Thanks in advance,
Cro
 


[SQL] instead of trigger in pg

2005-12-28 Thread J Crypter
Hi,

I would like to implement a 1:n relation between two
tables. 
An auto-generated number should be used as primary key
which connects both tables. 
Example:

table 1:
name | number (prim_key)

table 2:
country | number_table1 (foreign key)

View:
number_table1 | name | country 

I would like to insert into both tables in one step.
"Insert into view (name,
country)values('name','country');"

Oracle supports an instead-of-trigger but Postgres
doesn't do this.

CREATE or replace FUNCTION insertInto() RETURNS
trigger AS '
BEGIN
insert into table1(name)values(NEW.name);
insert into
table2(number,country)values(NEW.number,NEW.country);

RETURN NEW;
END;
' LANGUAGE plpgsql;

CREATE TRIGGER insert_TR BEFORE INSERT OR UPDATE ON
view
FOR EACH ROW EXECUTE PROCEDURE insertInto();


I would like to implement something like this but I
don't know how to do.

Thank you for you help!

Jakob






___ 
Telefonate ohne weitere Kosten vom PC zum PC: http://messenger.yahoo.de

---(end of broadcast)---
TIP 6: explain analyze is your friend


Re: [SQL] "large" IN/NOT IN subqueries result in query returning wrong data

2005-12-28 Thread Greg Stark
elein <[EMAIL PROTECTED]> writes:

> > Note that the above are not inverses because you changed the lefthand
> > input.  You do get consistent results when you just add or omit NOT:
> Yes, you are right. I skipped the permutations to get down to the point.

Remember that NULL means "unknown". So "1 IN (1,2,NULL)" *should* be true
because regardless of what that unknown value is it's still obvious that 1
really is in the list. And "3 NOT IN (1,2,NULL)" is unknown because it depends
on whether that unknown quantity is 3 or not.

IN is the same as "= ANY" so "1 IN (1,2,NULL)" is the same as 
"1=1 OR 1=2 OR 1=NULL" which is true even though the last of the three is null.



-- 
greg


---(end of broadcast)---
TIP 6: explain analyze is your friend


Re: [SQL] Cursors and recursion

2005-12-28 Thread Tom Lane
Don Croata <[EMAIL PROTECTED]> writes:
> It's a function who has a cursor and calls itself, but the problem raises
> after the first recursion, when PgSQL complains:

> ERROR:  cursor "cur" already in use

> Are the cursors kept globally? or cached like TEMP TABLE?

Cursor names are global within a particular session.

IIRC there is a syntax for opening a cursor without specifying a name,
in which case plpgsql will pick one that's not in use.  This is probably
what you want to use.

regards, tom lane

---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
   choose an index scan if your joining column's datatypes do not
   match


Re: [SQL] instead of trigger in pg

2005-12-28 Thread Jaime Casanova
On 12/28/05, J Crypter <[EMAIL PROTECTED]> wrote:
> Hi,
>
> I would like to implement a 1:n relation between two
> tables.
> An auto-generated number should be used as primary key
> which connects both tables.
> Example:
>
> table 1:
> name | number (prim_key)
>
> table 2:
> country | number_table1 (foreign key)
>
> View:
> number_table1 | name | country
>
> I would like to insert into both tables in one step.
> "Insert into view (name,
> country)values('name','country');"
>
> Oracle supports an instead-of-trigger but Postgres
> doesn't do this.
>

postgres uses rules for this situation... and yes there are INSTEAD OF rules...

> CREATE or replace FUNCTION insertInto() RETURNS
> trigger AS '
>BEGIN
>insert into table1(name)values(NEW.name);
>insert into
> table2(number,country)values(NEW.number,NEW.country);
>
>RETURN NEW;
>END;
> ' LANGUAGE plpgsql;
>
> CREATE TRIGGER insert_TR BEFORE INSERT OR UPDATE ON
> view
>FOR EACH ROW EXECUTE PROCEDURE insertInto();
>
>
> I would like to implement something like this but I
> don't know how to do.
>
> Thank you for you help!
>
> Jakob
>
>
>
>
>
>
> ___
> Telefonate ohne weitere Kosten vom PC zum PC: http://messenger.yahoo.de
>
> ---(end of broadcast)---
> TIP 6: explain analyze is your friend
>


--
Atentamente,
Jaime Casanova
(DBA: DataBase Aniquilator ;)

---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
   choose an index scan if your joining column's datatypes do not
   match


Re: [SQL] Cursors and recursion

2005-12-28 Thread Michael Fuhr
On Wed, Dec 28, 2005 at 10:48:25AM -0500, Tom Lane wrote:
> Don Croata <[EMAIL PROTECTED]> writes:
> > It's a function who has a cursor and calls itself, but the problem raises
> > after the first recursion, when PgSQL complains:
> 
> > ERROR:  cursor "cur" already in use
> 
> > Are the cursors kept globally? or cached like TEMP TABLE?
> 
> Cursor names are global within a particular session.
> 
> IIRC there is a syntax for opening a cursor without specifying a name,
> in which case plpgsql will pick one that's not in use.  This is probably
> what you want to use.

Or, if possible, use "FOR record_or_row IN query LOOP" instead of
an explicit cursor.

http://www.postgresql.org/docs/8.1/interactive/plpgsql-control-structures.html#PLPGSQL-RECORDS-ITERATING

-- 
Michael Fuhr

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


Re: [SQL] Cursors and recursion

2005-12-28 Thread Don Croata
Please, if someone recalls a link, book, piece of code or anything with info about this technique for PL/PgSQL (8.1), please let us know. We've been searching into google, groups.google, 
http://archives.postgresql.org and http://www.postgresql.org/docs/8.1/interactive with no results. Most of the answers are related to unclosed cursors for the "ERROR: cursor ... already in use" message.

 
Here's the sample code for this issue (i.e. error because cursor already defined in recursive PL/PgSQL function) at: http://www.croata.cl/cur.sql
 
--
 
Thanx again,
Cro
 
On 12/28/05, Tom Lane <[EMAIL PROTECTED]> wrote:
Don Croata <[EMAIL PROTECTED]> writes:> It's a function who has a cursor and calls itself, but the problem raises
> after the first recursion, when PgSQL complains:> ERROR:  cursor "cur" already in use> Are the cursors kept globally? or cached like TEMP TABLE?Cursor names are global within a particular session.
IIRC there is a syntax for opening a cursor without specifying a name,in which case plpgsql will pick one that's not in use.  This is probablywhat you want to use.   regards, tom lane



[SQL] DISTINCT with NULLs and INT fields

2005-12-28 Thread George Pavlov
What does The SQL Standard say about this one?

create table foo (a varchar, b int);

insert into foo (a, b) select null, null from bar;
-- no problem

insert into foo (a, b) select distinct null, null from bar;
-- ERROR:  column "b" is of type integer but expression is of type text
-- HINT:  You will need to rewrite or cast the expression.

It seems that applying DISTINCT makes the NULL be of type TEXT... I just
tried the exact same thing in Ms. SQL Server 2005 and it works with no
errors. Looks like SQL Server makes the NULLs be INTs, but is probably
better at doing the implicit conversion from INT. Any thoughts on what
the "correct" behavior should be here?

George

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


Re: [SQL] DISTINCT with NULLs and INT fields

2005-12-28 Thread Tom Lane
"George Pavlov" <[EMAIL PROTECTED]> writes:
> What does The SQL Standard say about this one?

> insert into foo (a, b) select distinct null, null from bar;
> -- ERROR:  column "b" is of type integer but expression is of type text

According to the SQL spec that query is illegal on its face --- the spec
does not allow a bare NULL keyword except in contexts where the datatype
is immediately evident.  You'd have had to write
SELECT DISTINCT CAST(NULL AS varchar), CAST(NULL AS int)
to be fully spec-conformant.

Postgres handles NULL the same way as untyped literals ('foo'), so we
tend to prefer resolving to type text when things are ambiguous.  In
this case the DISTINCT operation forces a type choice (if you don't know
what type the data is, you can hardly decide whether two values are equal
or not) and so by the time the INSERT sees it, it looks like a SELECT
of two text columns.

> Looks like SQL Server makes the NULLs be INTs, but is probably
> better at doing the implicit conversion from INT.

"Better" is in the eye of the beholder.  It surprises me not at all that
Microsoft would be lax about implicit coercions, but that doesn't make
it a good idea to coerce anything to anything else without complaint.
You might as well not have a type system at all, if you're going to
destroy its ability to detect mistakes that way.

regards, tom lane

---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
   choose an index scan if your joining column's datatypes do not
   match


Re: [SQL] DISTINCT with NULLs and INT fields

2005-12-28 Thread George Pavlov
> "Better" is in the eye of the beholder.  

sorry for the value-laden term. "laxer" is more appropriate, of course!
the funny thing is that had they cast the NULLs to TEXT it would have
failed there too (they do not do implicit TEXT to INT).

> It surprises me not  at all that
> Microsoft would be lax about implicit coercions, but that doesn't make
> it a good idea to coerce anything to anything else without complaint.
> You might as well not have a type system at all, if you're going to
> destroy its ability to detect mistakes that way.

indeed! but, wait, doesn't our favorite dbms do some implicit casting
too? continuing with my table foo (a varchar, b int):

test=# delete from foo;
DELETE 2
test=# insert into foo values (4,4);
INSERT 0 1
test=# insert into foo values ('4','4');
INSERT 0 1
test=# insert into foo values ('oh','no');
ERROR:  invalid input syntax for integer: "no"
test=# select * from foo;
 a | b
---+---
 4 | 4
 4 | 4
(2 rows)

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


Re: [SQL] DISTINCT with NULLs and INT fields

2005-12-28 Thread Tom Lane
"George Pavlov" <[EMAIL PROTECTED]> writes:
> indeed! but, wait, doesn't our favorite dbms do some implicit casting
> too? continuing with my table foo (a varchar, b int):

> test=# delete from foo;
> DELETE 2
> test=# insert into foo values (4,4);
> INSERT 0 1
> test=# insert into foo values ('4','4');
> INSERT 0 1
> test=# insert into foo values ('oh','no');
> ERROR:  invalid input syntax for integer: "no"

Sure, but in this example the required type of the value is clear from
immediate context (ie, the INSERT).  This is one of the cases where
the SQL spec requires a bare NULL to be accepted.  (BTW, 'no' and '4'
in this example are *not* values of type text; they are untyped literals
which we eventually resolve as varchar or int.)

The other case you mentioned is one where we are going out on a limb a
bit:

INSERT INTO foo SELECT NULL, NULL;

In this case we allow the SELECT to not force a type choice, so that the
INSERT sees the raw untyped values, but I think that this query is
probably illegal per spec --- I believe the spec requires a SELECT to
deliver well-defined data types.  Too lazy to go look up chapter and
verse at the moment.

regards, tom lane

---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
   choose an index scan if your joining column's datatypes do not
   match


Re: [SQL] DISTINCT with NULLs and INT fields

2005-12-28 Thread George Pavlov
> Sure, but in this example the required type of the value is clear from
> immediate context (ie, the INSERT).  This is one of the cases where
> the SQL spec requires a bare NULL to be accepted.  (BTW, 'no' and '4'
> in this example are *not* values of type text; they are 
> untyped literals which we eventually resolve as varchar or int.)

hmmm... with the risk of boring everyone to tears:

test=# insert into foo values (4::int,4::int);
INSERT 0 1
test=# insert into foo values (4::text,4::text);
ERROR:  column "b" is of type integer but expression is of type text
HINT:  You will need to rewrite or cast the expression.
test=# insert into foo values (cast(4 as int),cast(4 as int));
INSERT 0 1
test=# insert into foo values (cast(4 as text),cast(4 as text));
ERROR:  column "b" is of type integer but expression is of type text
HINT:  You will need to rewrite or cast the expression.

(i actually think it is important to understand how this stuff works and
thanks for explaining!) 

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

   http://www.postgresql.org/docs/faq


Re: [SQL] DISTINCT with NULLs and INT fields

2005-12-28 Thread Alvaro Herrera
George Pavlov wrote:

> test=# insert into foo values (4::int,4::int);
> INSERT 0 1
> test=# insert into foo values (4::text,4::text);
> ERROR:  column "b" is of type integer but expression is of type text
> HINT:  You will need to rewrite or cast the expression.
> test=# insert into foo values (cast(4 as int),cast(4 as int));
> INSERT 0 1
> test=# insert into foo values (cast(4 as text),cast(4 as text));
> ERROR:  column "b" is of type integer but expression is of type text
> HINT:  You will need to rewrite or cast the expression.

The last sentence (and the second one as well -- they are exactly
equivalent) exemplifies that there isn't an implicit typecase from text
to integer.  If you use single quotes instead of an explicit cast, the
literal is assumed to be of type "unknown", which _can_ be casted
automatically to integer.

-- 
Alvaro Herrerahttp://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly


[SQL] Help with simple query

2005-12-28 Thread Collin Peters
I have a simple table called notes which contains notes for users. 
The table has 4 columns:  note_id (auto-incrementing primary key),
user_id (foreign key to a users table), note (varchar), and
modified_date (timestamp).

Is there a nice simple query I can run that will return me a list of
all the *latest* notes for all users (users can have many notes in the
table)?  I'm trying to figure out a simple way of doing it but seem to
be having some mental block or there is no easy way to do it.

The following query will return me all the latest dates, but I can't
return the note_id or subject with it.
SELECT n.user_id, max(n.modified_date)
FROM notes n
GROUP by n.user_id
ORDER BY n.user_id

Is this simpler than I am making it?

Regards,
Collin

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

   http://www.postgresql.org/docs/faq


Re: [SQL] Help with simple query

2005-12-28 Thread Tom Lane
Collin Peters <[EMAIL PROTECTED]> writes:
> Is there a nice simple query I can run that will return me a list of
> all the *latest* notes for all users (users can have many notes in the
> table)?

You can use SELECT DISTINCT ON for that, if you don't mind using a
Postgres-only feature.  See the "weather reports" example in the SELECT
reference page.

If you want to stick to portable SQL, you can still do it, but it's
pretty ugly and slow.  Look in the list archives for previous
discussions.

regards, tom lane

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly


Re: [SQL] Help with simple query

2005-12-28 Thread Frank Bax

At 06:58 PM 12/28/05, Collin Peters wrote:

The following query will return me all the latest dates, but I can't
return the note_id or subject with it.
SELECT n.user_id, max(n.modified_date)
FROM notes n
GROUP by n.user_id
ORDER BY n.user_id

Is this simpler than I am making it?



No, it's not "simple".  You need to join the results of above sql back to 
the original table (and relocate the order by clause):


SELECT notes.note_id, notes.user_id, maxx.max_date, notes.note
FROM
(SELECT n.user_id, max(n.modified_date) AS max_date FROM notes n GROUP by 
n.user_id)

AS maxx
JOIN notes on notes.user_id = maxx.user_id AND notes.modified_date = 
maxx.max_date
ORDER BY notes.user_id; 



---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
  choose an index scan if your joining column's datatypes do not
  match


Re: [SQL] Help with simple query

2005-12-28 Thread PFC
If you want the latest by user, you can cheat a bit and use the fact that  
the id's are incrementing, thus ordering by the id
is about the same as ordering by the date field. I know it can be inexact  
in some corner cases, but it's a good approximation, and

very useful in practice :

SELECT user_id, max(note_id) FROM notes GROUP by user_id;

So :

SELECT * FROM notes WHERE id IN (SELECT max(note_id) FROM notes GROUP by  
user_id) ;


Can postgres use the index on these max() clauses now ?


---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [SQL] Help with simple query

2005-12-28 Thread George Pavlov
or, from the "stupid tricks" category:

 SELECT
   n.user_id, 
   max(lpad(extract(epoch from n.modified_date),12,'0') || ' ' || note)
 FROM notes n
 GROUP by n.user_id

i am not *really* suggesting this!

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


Re: [SQL] DISTINCT with NULLs and INT fields

2005-12-28 Thread George Pavlov
> > test=# insert into foo values (4::int,4::int);
> > INSERT 0 1

> > test=# insert into foo values (4::text,4::text);
> > ERROR:  column "b" is of type integer but expression is of type text
> > HINT:  You will need to rewrite or cast the expression.

> > test=# insert into foo values (cast(4 as int),cast(4 as int));
> > INSERT 0 1

> > test=# insert into foo values (cast(4 as text),cast(4 as text));
> > ERROR:  column "b" is of type integer but expression is of type text
> > HINT:  You will need to rewrite or cast the expression.
> 
> The last sentence (and the second one as well -- they are exactly
> equivalent) exemplifies that there isn't an implicit typecase 
> from text
> to integer.  If you use single quotes instead of an explicit cast, the
> literal is assumed to be of type "unknown", which _can_ be casted
> automatically to integer.

yes, #1 is the same as #3, and #2 is the same as #4. i was trying to
provide a counter example to tom's statement that pgsql does not do type
coercions. the interesting thing here is that 4::int gets into a text
field whereas 4::text does not get into an integer field. seems to me
like there is an implicit int-to-text cast (without a symmetrical
text-to-int one) unless 4::int is somehow *still* considered an 'untyped
literal' (4 and '4' seem untyped to me, but 4::int does not)??

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


Re: [SQL] Cursors and recursion

2005-12-28 Thread Michael Fuhr
On Wed, Dec 28, 2005 at 04:37:21PM -0300, Don Croata wrote:
> Please, if someone recalls a link, book, piece of code or anything with info
> about this technique for PL/PgSQL (8.1), please let us know. We've been
> searching into google, groups.google, http://archives.postgresql.org and
> http://www.postgresql.org/docs/8.1/interactive with no results. Most of the
> answers are related to unclosed cursors for the "ERROR: cursor ... already
> in use" message.

See the "Cursors" section of the PL/pgSQL documentation and read
about unbound cursors:

http://www.postgresql.org/docs/8.1/interactive/plpgsql-cursors.html

"Note:  A bound cursor variable is initialized to the string value
representing its name, so that the portal name is the same as the
cursor variable name, unless the programmer overrides it by assignment
before opening the cursor.  But an unbound cursor variable defaults
to the null value initially, so it will receive an automatically-generated
unique name, unless overridden."

For example, instead of

  DECLARE
  cur CURSOR FOR SELECT ...;
  BEGIN
  OPEN cur;

use

  DECLARE
  cur refcursor;
  BEGIN
  OPEN cur FOR SELECT ...;

But as I mentioned in a previous post, it's usually easier to use
FOR-IN-LOOP.

-- 
Michael Fuhr

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

   http://www.postgresql.org/docs/faq


Re: [SQL] DISTINCT with NULLs and INT fields

2005-12-28 Thread Tom Lane
"George Pavlov" <[EMAIL PROTECTED]> writes:
> the interesting thing here is that 4::int gets into a text
> field whereas 4::text does not get into an integer field. seems to me
> like there is an implicit int-to-text cast (without a symmetrical
> text-to-int one)

Yeah, there is.  You can easily see the list of implicit casts for
yourself:

select castsource::regtype, casttarget::regtype from pg_cast
where castcontext = 'i' and castsource != casttarget;

There's 90 of them in current CVS tip, and most of 'em are unsurprising
within-type-category casts, such as implicit promotion of int to bigint.
However we have about a dozen implicit casts to text from the numeric
and datetime type categories.  Personally I would dearly love to get
rid of these, because they are accidents waiting to happen (and they
do regularly bite people, see the mail list archives for evidence).
But it seems people expect to be able to do things like
number || ' string'
without explicitly casting the number to text.

regards, tom lane

---(end of broadcast)---
TIP 6: explain analyze is your friend


Re: [SQL] constraint and ordered value

2005-12-28 Thread Bruno Wolff III
On Wed, Dec 28, 2005 at 00:52:18 +0700,
  David Garamond <[EMAIL PROTECTED]> wrote:
> Is it possible to use only CHECK constraint (and not triggers) to
> completely enforce ordered value of a column (colx) in a table? By that
> I mean:
> 
> 1. Rows must be inserted in the order of colx=1, then colx=2, 3, and so on;
> 
> 2. When deleting (or updating), "holes" must not be formed, e.g. if
> there are three rows then row with colx=3 must be the first one deleted,
> and then colx=2 the second, and so on.
> 
> I can see #1 being accomplished using a NOT NULL + UNIQUE constraint and
> a CHECK constraint that calls some PL function where the function does a
> simple checking (new.colx=1 if COUNT(colx)==0, or new.colx=MAX(colx)+1).
> 
> But is it possible to do #2 using only constraints?

No. A constraint only applies to one row at a time. If you try to work around
this by calling a function that does queries it isn't guarenteed to work.
And if you are thinking of calling a function that does a query, you aren't
looking at saving time over using triggers.

Also, if you are going to have concurrent updates, you are going to need to
do table locking to make this work.

---(end of broadcast)---
TIP 6: explain analyze is your friend