[SQL] casting to arrays
I have a rather odd table structure that I would like to simplify to be a view (for some definition of simplify). The current idea I have is to shovel values from multiple rows in one table into an array in the view. The tables look something like this: create table person ( id serial, name varchar ); create table stuff ( person_id references person (id) on delete restrict, stuff_name varchar ); The view would go something like: create view person_with_stuff as select p.id as id, p.name as name, ( select s.stuff_name from stuff where s.person_id = p.id )::varchar[] from person p; Is anything like this possible? I know this may not be good form, but unfortunately (or perhaps fortunately, since it means I have a job) there are business reasons for this, supporting old apps and such. Thanks in advance! -- Mike Rylander ---(end of broadcast)--- TIP 9: the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
Re: [SQL] casting to arrays
Thank you! This is great news. Is there a projected release date for 7.4?
Also, is there a published roadmap, or should I just get on the developers
list?
Thanks again.
---
Mike Rylander
On Friday 18 July 2003 05:34 pm, Joe Conway wrote:
> Mike Rylander wrote:
> > I have a rather odd table structure that I would like to simplify to be a
> > view (for some definition of simplify). The current idea I have is to
> > shovel values from multiple rows in one table into an array in the view.
> > The tables look something like this:
>
>
>
> > Is anything like this possible? I know this may not be good form, but
> > unfortunately (or perhaps fortunately, since it means I have a job) there
> > are business reasons for this, supporting old apps and such.
>
> Not possible in current releases, but it will be in 7.4 (about to start
> beta). It looks like this:
>
> create table person (id integer, name varchar);
> insert into person values(1,'Bob');
> insert into person values(2,'Sue');
>
> create table stuff (person_id integer, stuff_name text);
> insert into stuff values(1,'chair');
> insert into stuff values(1,'couch');
> insert into stuff values(1,'lamp');
> insert into stuff values(2,'table');
> insert into stuff values(2,'shirt');
>
> create or replace view person_with_stuff as select p.id as id, p.name as
> name, ARRAY(select s.stuff_name from stuff s where s.person_id = p.id)
> as stuff from person p;
>
> regression=# select * from person_with_stuff;
> id | name | stuff
> +--+
>1 | Bob | {chair,couch,lamp}
>2 | Sue | {table,shirt}
> (2 rows)
>
> HTH,
>
> Joe
---(end of broadcast)---
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])
Re: [SQL] converting interval to timestamp
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 If the number of seconds between timestamps is acceptable then this is the solution I use: SELECT ABS(EXTRACT(EPOCH FROM t.field1) - EXTRACT(EPOCH FROM t.field2)) AS diff FROM table AS t; Adjust to your column and WHERE needs. One caveat: this only works for dates within the UNIX epoch ( after 1969-12-31). On Thursday 31 July 2003 12:05 pm, teknokrat wrote: > The difference of two dates/timestamps always gives an interval. is > there a way to convert this interval into number such as number of > milliseconds or number of days? > > Also does anyone know what field type an interval would map to in jdbc? > > thanks > > > > ---(end of broadcast)--- > TIP 9: the planner will ignore your desire to choose an index scan if your > joining column's datatypes do not match - -- Mike Rylander -BEGIN PGP SIGNATURE- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE/KmAOgRDV1fFA+3cRAgbVAJ9B03Pxsn+N+Xg2C/a4gw3j28KSsgCeNA7+ y2rYedgRdTY/BiNSfVJTvOs= =kVkm -END PGP SIGNATURE- ---(end of broadcast)--- TIP 5: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faqs/FAQ.html
Re: [SQL] new max function
Here's mine: CREATE FUNCTION max2 (INTEGER,INTEGER) RETURNS INTEGER LANGUAGE SQL AS 'SELECT CASE WHEN $1 > $2 THEN $1 ELSE $2 END'; This returns: database=# select max2(1,2); max2 -- 2 (1 row) database=# select max2(3,1); max2 -- 3 (1 row) On Friday 17 October 2003 02:13 pm, Rodrigo Gesswein wrote: > Hello! > >I'm looking for a function to calculate the max value from two numbers, > something like max2(a,b) with a,b int > >Does anyone have the trick ? > >Thank you in advance.. > > Rodrigo! > > ---(end of broadcast)--- > TIP 3: 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 -- Mike Rylander ---(end of broadcast)--- TIP 6: Have you searched our list archives? http://archives.postgresql.org
Re: [SQL] How do i extract a certain bit from a bigint column
On Wednesday 12 May 2004 07:05 am, Mats Sjöberg wrote: > Hello everyone > In a table i have a column status of type bigint. > I need to create a view of the table including all rows with bit 4 set > (value 8). > At the same time i need to exclude excludig all rows with bit 2 set. > > What is the syntax to extract those bits? > I have tested get_bit(string, offset) but this requires a string, and not a > bigint. > Is there a function to The easiest way is to test for a bit using bitwise and: SELECT * FROM table WHERE (status & 2::BIGINT) <> 0 AND (status & 8::BIGINT) = 0; -miker ---(end of broadcast)--- TIP 5: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faqs/FAQ.html
Re: [SQL] [HACKERS] MERGE-esque Functionallity (was: Adding MERGE to the TODO list (resend with subject))
On Tuesday 11 May 2004 09:44 am, Bruce Momjian wrote: [snip] > > > > Bruce Momjian kirjutas E, 10.05.2004 kell 06:58: > > > > > Added to TODO: > > > > > > > > > > * Add MERGE command that does UPDATE, or on failure, INSERT > > > > [snip] Hello all. I have been lurking here for a bit and the MERGE topic (on [HACKERS]) caught my eye, so I had a go at implementing a basic version of MERGE-on-INSERT in pl/pgsql. It is attached below, and any comments are welcome. I find it useful on "status" type tables, though it is not very nice when there are many clients (table locking to avoid race conditions). Hope someone will find it useful! -miker -- -- Merge on INSERT functionallity for Postgres 7.3+ -- -- [EMAIL PROTECTED] / 5-14-04 -- -- CAVEAT EMPTOR: Uses table locks to avoid concurrency issues, -- so it WILL slow down heavily loaded tables. -- This effecivly puts the table into -- TRANSACTION ISOLATION LEVEL SERIALIZABLE mode. -- CREATE OR REPLACE FUNCTION add_merge_on_insert ( TEXT, -- table name TEXT, -- key column TEXT[] -- column list to update on deduplication ) RETURNS TEXT RETURNS NULL ON NULL INPUT SECURITY INVOKER LANGUAGE 'plpgsql' AS ' DECLARE tablename ALIAS FOR $1; keycol ALIAS FOR $2; updatecols ALIAS FOR $3; trig TEXT; arraydims TEXT; BEGIN trig := \' CREATE FUNCTION "\' || tablename || \'_merge_on_insert_proc" () RETURNS TRIGGER AS \'\' DECLARE orig \' || quote_ident(tablename) || \'%ROWTYPE; BEGIN LOCK TABLE \' || quote_ident(tablename) || \' IN ROW EXCLUSIVE MODE; SELECT INTO orig * FROM \' || quote_ident(tablename) || \' WHERE \' || quote_ident(keycol)|| \' = NEW.\' || quote_ident(keycol) || \'; IF NOT FOUND THEN RETURN NEW; END IF; UPDATE \' || quote_ident(tablename) || \' SET \'; arraydims := array_dims(updatecols); FOR i IN 1 .. (substring(arraydims from (position(\':\' in arraydims) + 1 ) for ( position(\']\' in arraydims) - (position(\':\' in arraydims) + 1 ) )))::INT LOOP trig := trig || quote_ident(updatecols[i]) || \' = COALESCE( NEW.\' || quote_ident(updatecols[i]) || \', orig.\' || quote_ident(updatecols[i]) || \'), \'; END LOOP; trig := substring( trig from 0 for (character_length(trig) - 1)); trig := trig || \' WHERE \' || quote_ident(keycol)|| \' = NEW.\' || quote_ident(keycol) || \'; RETURN NULL; END; \'\' LANGUAGE \'\'plpgsql\'\'; \'; EXECUTE trig; EXECUTE \' CREATE TRIGGER "\' || tablename || \'_merge_on_insert_trig" BEFORE INSERT ON \' || quote_ident(tablename) || \' FOR EACH ROW EXECUTE PROCEDURE "\' || tablename || \'_merge_on_insert_proc" (); \'; RETURN \'FUNCTION \' || tablename || \'_merge_on_insert_proc (); TRIGGER \' || tablename || \'_merge_on_insert_trig;\'; END; '; CREATE OR REPLACE FUNCTION remove_merge_on_insert ( TEXT -- table name ) RETURNS TEXT RETURNS NULL ON NULL INPUT SECURITY INVOKER LANGUAGE 'plpgsql' AS ' BEGIN EXECUTE \'DROP FUNCTION "\' || $1 || \'_merge_on_insert_proc" () CASCADE;\'; RETURN \'FUNCTION \' || $1 || \'_merge_on_insert_proc (); TRIGGER \' || $1 || \'_merge_on_insert_trig;\'; END; '; ---(end of broadcast)--- TIP 7: don't forget to increase your free space map settings
Re: [SQL] Trigger problem
kasper wrote: > Hi guys > > Im tryint to make a trigger that marks a tuble as changed whenever someone > has updated it > > my table looks something like this > > create table myTable ( > ... > changed boolean; > ) > > now ive been working on a trigger and a sp that looks like this, but it > doesnt work... > > create function myFunction returns trigger as ' > begin > new.changed = true; The line above is using the SQL equaliy opperator, you want the assignment operator: := as in new.changed := true; > return new; > end; > ' language 'plpgsql'; > > create trigger myTrigger > after update on lektioner > for each row > execute procedure myFunction(); > > > the code compiles, runs, and doesnt whine about anything, but nothing > changes... > > any ideas?? > > - Kasper -miker ---(end of broadcast)--- TIP 7: don't forget to increase your free space map settings
Re: [SQL] How to filter on timestamps?
B.W.H. van Beest wrote: > > > I have a table where one of the columns is of type 'TIMESTAMP' > > How can I do a query to filter on the TIMESTAMP value, e.g. to obtain > all rows earlier than a certain time stamp? Think of the math opperators '<' and '>' as 'before' and 'after', respectively. ie: SELECT * FROM table WHERE begin_date > '2004-07-06'; You can also use BETWEEN: SELECT * FROM table WHERE update_timestamp BETWEEN '2004-07-01' AND '2004-07-06'; Remember that when timestamps are cast to dates, they are cast with 00:00:00.0 as the time part. See the docs on this at http://www.postgresql.org/docs/7.4/interactive/datatype-datetime.html and http://www.postgresql.org/docs/7.4/interactive/functions-datetime.html . --miker > > Regards, ---(end of broadcast)--- TIP 4: Don't 'kill -9' the postmaster
Re: [SQL] implementing an out-of-transaction trigger
>I've come across a situation where I'd like to use some kind of "out-of-transaction >trigger" to do some processing after changes to some tables, but without extending >the duration of the main transaction. Of course, it's important that the processing be >completed so it has to be, as far as possible, reliable and "safe". The extra >processing should be completed within a reasonable time after the original >transaction, but it needn't happen immediately. Check out http://www.postgresql.org/docs/7.4/static/sql-listen.html and http://www.postgresql.org/docs/7.4/static/sql-notify.html Then look at the Rules system for generating a NOTIFY: http://www.postgresql.org/docs/7.4/static/sql-createrule.html --miker ---(end of broadcast)--- TIP 7: don't forget to increase your free space map settings
Re: [SQL] sql
On Mon, 25 Oct 2004 10:13:37 +0200, cristivoinicaru <[EMAIL PROTECTED]> wrote: > I have a postgres table like this: > > CREATE TABLE "temp50" ( > "gc" character varying(36), > "co" character varying(7), > "data" date, > "ora" smallint > > ); > > It contains the following records: > > 5003707G9G9419 22012BB 10-14-2004 82 > 5003707G9G9419 22012BC 10-14-2004 44 > 5003707G9G9419 22022BB 10-14-2004 82 > 5003707G9G9420 22022BC 10-18-2004 49 > > I'd like the result of the sql interogation to be like this: > > 5003707G9G9419 22012BB 10-14-2004 82 > 5003707G9G9420 22022BC 10-18-2004 49 > > Explanations: > I want like sql interogation to select only one record from each "gc" group > record (who has the same code "gc" (that means that the "gc" field will be > unique key)) with the following two condition: > 1)from each "gc" group of records to select the record who has the value of > "ora" field maxim. > 2)if two ore more record have the same value of the maxim value of the "ora" > to select oly one of them Try: SELECT * FROM temp50 GROUP BY gc ORDER BY ora DESC; --miker > > Thanks! > > ---(end of broadcast)--- > TIP 8: explain analyze is your friend > ---(end of broadcast)--- TIP 8: explain analyze is your friend
Re: [SQL] sql
On Mon, 25 Oct 2004 05:44:06 -0600, Andrew J. Kopciuch <[EMAIL PROTECTED]> wrote: > On Monday 25 October 2004 05:20, Mike Rylander wrote: > > SELECT * FROM temp50 GROUP BY gc ORDER BY ora DESC; > > You can not have have expressions (columns etc.) in the SELECT list that are > either not in a GROUP BY clause, or used in an aggregate function when you > use GROUP BY in the statement. By saying SELECT *, means you would have to > GROUP BY gc, co, data, ora ... Doh! Of course. Should have had coffee before writing that ;) > > That isn't going to do what he wants. And the SQL you stated should give you > an error: > > ERROR: column "temp50.co" must appear in the GROUP BY clause or be used in an > aggregate function > > What he wants to do is use DISTINCT ON: > > SELECT DISTINCT ON (gc) gc, co, data, ora FROM temp50 ORDER BY gc, ora DESC; > > Andy > ---(end of broadcast)--- TIP 2: you can get off all lists at once with the unregister command (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])
Re: [SQL] tree structure photo gallery date quiery
p1.lft between p2.lft and p2.rgt and p1.id = 7; > id | parent |name > ++ > 1 | 0 | Root > 3 | 1 | Middleton > 7 | 3 | From The Footplate > (3 rows) > > -- Select parent and subordinates - also want to convert to view > nymr=# select p1.*, g.* from tree as p1, tree as p2, gallery g where > g.id = p1.id and p1.lft between p2.lft and p2.rgt and p2.id = 1; > id | lft | rgt | id | parent |name > +-+-+++ > 1 | 1 | 14 | 1 | 0 | Root > 2 | 2 | 9 | 2 | 1 | NYMR > 3 | 10 | 13 | 3 | 1 | Middleton > 4 | 3 | 4 | 4 | 2 | Steam Gala > 5 | 5 | 6 | 5 | 2 | Diesel Gala > 6 | 7 | 8 | 6 | 2 | From The Footplate > 7 | 11 | 12 | 7 | 3 | From The Footplate > (7 rows) > > -- use the one above to select photos - another view > nymr=# select count(pid), max(added) from photos where id in ( > nymr(# select p1.id from tree as p1, tree as p2 where p1.lft between > p2.lft and p2.rgt and p2.id = 1 > nymr(# ); > count | max > ---+ > 4 | 2004-11-10 12:12:00+00 > (1 row) > > nymr=# select count(pid), max(added) from photos where id in ( > nymr(# select p1.id from tree as p1, tree as p2 where p1.lft between > p2.lft and p2.rgt and p2.id = 2 > nymr(# ); > count | max > ---+ > 3 | 2004-11-10 12:12:00+00 > (1 row) > > nymr=# select count(pid), max(added) from photos where id in ( > nymr(# select p1.id from tree as p1, tree as p2 where p1.lft between > p2.lft and p2.rgt and p2.id = 3 > nymr(# ); > count | max > ---+ > 1 | 2004-01-01 09:12:12+00 > (1 row) > > Here is the photo_count function, photo_updates just has differnt > attribute names/types > > create function photo_count(int4) returns int4 as 'DECLARE > gallery_id alias for $1; > pcount int4; > begin > select count(pid) into pcount from photos where id in ( > select p1.id from tree as p1, tree as p2 where p1.lft between p2.lft > and p2.rgt and p2.id = gallery_id > ); > return pcount; > end' language 'plpgsql'; > > > > -- > Gary Stainburn > > This email does not contain private or confidential material as it > may be snooped on by interested government parties for unknown > and undisclosed purposes - Regulation of Investigatory Powers Act, 2000 > > ---(end of broadcast)--- > TIP 3: 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 > -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer ---(end of broadcast)--- TIP 2: you can get off all lists at once with the unregister command (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])
Re: [SQL] Recursive SETOF function
I'm feeling sausey today, so here is my (untested) attempt to translate your function. It's inline below, and you'll want to look here http://www.postgresql.org/docs/7.4/interactive/plpgsql.html for more information. On Mon, 22 Nov 2004 09:18:13 -0600, Richard Rowell <[EMAIL PROTECTED]> wrote: > I'm trying to port some TSQL to PLPGSQL. The DB has a table with a > recursive foreign key that represents a tree hierarchy. I'm trying to > re-create a TSQL function that pulls out all the ancestors of a given > node in the hierarchy. > > I'm rather new to PLSQL and I have several questions. > > 1. In TSQL, I can assign a scalar to the result of query like so: > SET @var1 = (SELECT foo FROM bar WHERE [EMAIL PROTECTED]) > > How would I do this in PLSQL? > > 2. In TSQL the "result table" can be inserted into manually. IE: > > CREATE FUNCTION foo () RETURNS @ttable TABLE( uid INTEGER) AS BEGIN > INSERT @ttable VALUES (1) > RETURN > END > > Is there a way to manually insert rows into the result table in PLSQL? > > What follows is my TSQL function if that helps give context. > > CREATE FUNCTION svp_getparentproviderids (@child_provider INTEGER) > RETURNS @provider_ids TABLE ( uid INTEGER ) > AS > BEGIN > DECLARE @cid AS INTEGER > IF (SELECT count(*) FROM providers WHERE uid [EMAIL PROTECTED]) > 0 > BEGIN > SET @cid = @child_provider > WHILE @cid IS NOT NULL > BEGIN > INSERT @provider_ids VALUES (@cid) > SET @cid = (SELECT parent_id FROM providers WHERE [EMAIL > PROTECTED]) > END > END > RETURN > END > -- This TYPE will get you a named column... easier to use SRFs with a preexisting type. CREATE TYPE svp_getparentproviderids_uid_type AS ( uid INTEGER ); CREATE FUNCTION svp_getparentproviderids (INTEGER) RETURNS SETOF svp_getparentproviderids_uid_type AS ' DECLARE child_provider ALIAS FOR $1; cid INTEGER; BEGIN SELECT count(*) FROM providers WHERE uid [EMAIL PROTECTED]) > 0 LOOP cid := child_provider IF cid IS NULL THEN EXIT; END IF; RETURN NEXT cid; SELECT INTO cid parent_id FROM providers WHERE [EMAIL PROTECTED]; END LOOP; RETURN END;' LANGUAGE 'plpgsql'; Hope that helps! > -- > > ---(end of broadcast)--- > TIP 3: 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 > -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer ---(end of broadcast)--- TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]
Re: [SQL] Recursive SETOF function
Forgot one line. See below On Mon, 22 Nov 2004 11:54:30 -0500, Mike Rylander <[EMAIL PROTECTED]> wrote: > I'm feeling sausey today, so here is my (untested) attempt to [snip] > > CREATE FUNCTION svp_getparentproviderids (@child_provider INTEGER) > > RETURNS @provider_ids TABLE ( uid INTEGER ) > > AS > > BEGIN > > DECLARE @cid AS INTEGER > > IF (SELECT count(*) FROM providers WHERE uid [EMAIL PROTECTED]) > 0 > > BEGIN > > SET @cid = @child_provider > > WHILE @cid IS NOT NULL > > BEGIN > > INSERT @provider_ids VALUES (@cid) > > SET @cid = (SELECT parent_id FROM providers WHERE [EMAIL > > PROTECTED]) > > END > > END > > RETURN > > END > > > > -- This TYPE will get you a named column... easier to use SRFs with a > preexisting type. > CREATE TYPE svp_getparentproviderids_uid_type AS ( uid INTEGER ); > > CREATE FUNCTION svp_getparentproviderids (INTEGER) >RETURNS SETOF svp_getparentproviderids_uid_type >AS ' > DECLARE > child_provider ALIAS FOR $1; > cid INTEGER; > BEGIN SELECT * FROM providers WHERE uid [EMAIL PROTECTED]) > 0 IF NOT FOUND RETURN; END IF; > LOOP > cid := child_provider > IF cid IS NULL THEN > EXIT; > END IF; > RETURN NEXT cid; > SELECT INTO cid parent_id FROM providers WHERE [EMAIL PROTECTED]; > END LOOP; > RETURN > END;' LANGUAGE 'plpgsql'; > > Hope that helps! > > > -- > > > > > > ---(end of broadcast)--- > > TIP 3: 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 > > > > > -- > Mike Rylander > [EMAIL PROTECTED] > GPLS -- PINES Development > Database Developer > -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer ---(end of broadcast)--- TIP 2: you can get off all lists at once with the unregister command (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])
Re: [postgres] Re: [SQL] Recursive SETOF function
Sorry about that... try this: CREATE OR REPLACE FUNCTION svp_getparentproviderids (INTEGER) RETURNS SETOF svp_getparentproviderids_uid_type AS ' DECLARE child_provider ALIAS FOR $1; cid svp_getparentproviderids_uid_type%ROWTYPE; tmp_cid INTEGER; BEGIN SELECT INTO tmp_cid count(*) FROM providers WHERE uid =child_provider; IF tmp_cid = 0 THEN RAISE EXCEPTION ''Inexistent ID --> %'', child_provider; RETURN; END IF; cid.uid := child_provider; LOOP EXIT WHEN tmp_cid IS NULL; RETURN NEXT cid; SELECT INTO tmp_cid parent_id FROM providers WHERE uid=cid.uid; END LOOP; RETURN; END;' LANGUAGE 'plpgsql'; On Mon, 22 Nov 2004 12:51:41 -0600, Richard Rowell <[EMAIL PROTECTED]> wrote: > I have been fiddling with what you sent. I have it working mostly, save > for I keep getting syntax errors on the "RETURN NEXT cid;" line. If I > remove this line then the function works ( but returns nothing of > course). Any ideas? > > sp_demo_505=# CREATE OR REPLACE FUNCTION svp_getparentproviderids > (INTEGER) >RETURNS SETOF svp_getparentproviderids_uid_type >AS ' > DECLARE > child_provider ALIAS FOR $1; > cid INTEGER; > BEGIN > SELECT INTO cid count(*) FROM providers WHERE uid =child_provider; > IF cid = 0 THEN > RAISE EXCEPTION ''Inexistent ID --> %'', child_provider; > RETURN; > END IF; > cid := child_provider; > LOOP > EXIT WHEN cid IS NULL; > RETURN NEXT cid; > SELECT INTO cid parent_id FROM providers WHERE uid=cid; > END LOOP; > RETURN; > END;' LANGUAGE 'plpgsql'; > CREATE FUNCTION > sp_demo_505=# select * from svp_getparentproviderids(21112); > ERROR: incorrect argument to RETURN NEXT at or near "cid" > CONTEXT: compile of PL/pgSQL function "svp_getparentproviderids" near > line 13 > > -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer ---(end of broadcast)--- TIP 4: Don't 'kill -9' the postmaster
Re: [SQL] Breadth first traversal in PLSQL (How to implement Queue?)
On Wed, 15 Dec 2004 12:54:44 -0600, Richard Rowell <[EMAIL PROTECTED]> wrote: > I have a table with a unary (recursive) relationship that represents a > hierarchy. With the gracious help of Mike Rylander I was able to port a > TSQL function that would traverse "up" the hierarchy to PL/SQL. Now I > need help porting the "down" the hierarchy function. Glad I could help! > > As implemented in TSQL I utilized a simple breadth first tree traversal. > I'm not sure how to replicate this in PL/SQL as I haven't figured out > how to implement the queue required for the breadth first algorithm. My > queue is declared "queue SETOF INTEGER" and I'm able to "SELECT INTO" > this variable. However when I try to delete the "current" value, I get > a syntax error. If I comment the delete out, I also get an error when I > try to fetch the "next" value from the front of the queue. > You probably want to use a temp table to hold the queue. Edits inline below. > Below is the function, followed by the psql output: > > CREATE OR REPLACE FUNCTION svp_getchildproviderids (INTEGER) > RETURNS SETOF INTEGER > AS ' > DECLARE > parent_provider ALIAS FOR $1; > cid INTEGER; -- Comment out the next line... -- queue SETOF INTEGER; > BEGIN -- We need to use execute to create the queue, otherwise -- the OID will be cached and the next invocation will cause -- an exception. EXECUTE ''CREATE TEMP TABLE cid_queue (id SERIAL, cid INTEGER ) WITHOUT OIDS;''; >SELECT INTO cid count(*) FROM providers WHERE uid =parent_provider; >IF cid = 0 THEN >RAISE EXCEPTION ''Inexistent ID --> %'', parent_provider; >RETURN; >END IF; >cid := parent_provider; >LOOP >EXIT WHEN cid IS NULL; >RETURN NEXT cid; -- Put the CID into the queue EXECUTE ''INSERT INTO cid_queue VALUES ((SELECT uid FROM providers WHERE parent_id = '' || quote_literal( cid ) || ''));''; -- We'll use EXECUTE to delete the current cid from the queue EXECUTE ''DELETE FROM cid_queue WHERE cid = '' || quote_literal( cid ) || '';''; -- And a short loop to grab the next one FOR cid IN EXECUTE ''SELECT cid FROM cid_queue ORDER BY id LIMIT 1;'' END LOOP; >END LOOP; >RETURN; > END;' LANGUAGE 'plpgsql'; Let me know if that works. As before, it's untested, so YMMV... :) -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer http://open-ils.org ---(end of broadcast)--- TIP 8: explain analyze is your friend
Re: [SQL] Breadth first traversal in PLSQL (How to implement Queue?)
Arg! One more change below On Wed, 15 Dec 2004 21:48:57 -0500, Mike Rylander <[EMAIL PROTECTED]> wrote: > On Wed, 15 Dec 2004 12:54:44 -0600, Richard Rowell > <[EMAIL PROTECTED]> wrote: > > I have a table with a unary (recursive) relationship that represents a > > hierarchy. With the gracious help of Mike Rylander I was able to port a > > TSQL function that would traverse "up" the hierarchy to PL/SQL. Now I > > need help porting the "down" the hierarchy function. > > Glad I could help! > > > > > As implemented in TSQL I utilized a simple breadth first tree traversal. > > I'm not sure how to replicate this in PL/SQL as I haven't figured out > > how to implement the queue required for the breadth first algorithm. My > > queue is declared "queue SETOF INTEGER" and I'm able to "SELECT INTO" > > this variable. However when I try to delete the "current" value, I get > > a syntax error. If I comment the delete out, I also get an error when I > > try to fetch the "next" value from the front of the queue. > > > > You probably want to use a temp table to hold the queue. Edits inline below. > > > Below is the function, followed by the psql output: > > > > CREATE OR REPLACE FUNCTION svp_getchildproviderids (INTEGER) > > RETURNS SETOF INTEGER > > AS ' > > DECLARE > > parent_provider ALIAS FOR $1; > > cid INTEGER; > > -- Comment out the next line... > -- queue SETOF INTEGER; > > > BEGIN > > -- We need to use execute to create the queue, otherwise > -- the OID will be cached and the next invocation will cause > -- an exception. > EXECUTE ''CREATE TEMP TABLE cid_queue >(id SERIAL, cid INTEGER ) WITHOUT OIDS;''; > > >SELECT INTO cid count(*) FROM providers WHERE uid =parent_provider; > >IF cid = 0 THEN > >RAISE EXCEPTION ''Inexistent ID --> %'', parent_provider; > >RETURN; > >END IF; > >cid := parent_provider; > >LOOP > >EXIT WHEN cid IS NULL; > >RETURN NEXT cid; > > -- Put the CID into the queue > EXECUTE ''INSERT INTO cid_queue VALUES >((SELECT uid FROM providers WHERE > parent_id = '' || > quote_literal( cid ) || ''));''; > > -- We'll use EXECUTE to delete the current cid from the queue > EXECUTE ''DELETE FROM cid_queue WHERE cid = '' || > quote_literal( cid ) || '';''; > > -- And a short loop to grab the next one >FOR cid IN EXECUTE ''SELECT cid FROM cid_queue ORDER BY id LIMIT > 1;'' >END LOOP; > > >END LOOP; -- We need to drop the temp table, since this will probably be called -- more than once in a transaction. EXECUTE ''DROP TABLE cid_queue;''; > >RETURN; > > END;' LANGUAGE 'plpgsql'; > > Let me know if that works. As before, it's untested, so YMMV... :) > > -- > Mike Rylander > [EMAIL PROTECTED] > GPLS -- PINES Development > Database Developer > http://open-ils.org > -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer http://open-ils.org ---(end of broadcast)--- TIP 6: Have you searched our list archives? http://archives.postgresql.org
Re: [SQL] Constraint on 2 column possible?
On Thu, 27 Jan 2005 13:44:32 +0200, Andrei Bintintan <[EMAIL PROTECTED]> wrote: > > Hi, > > I have a table: > CREATE TABLE werke1( > id SERIAL, > id_hr int4 NOT NULL, > id_wk int4 NOT NULL > ); > > CREATE TABLE contact( > id SERIAL, > type varchar(20), > ); > > > Now id_hr and id_wk are all referencing the same table contact(id). In the > contact table I have another column called type. > How can I write a constraint that checks that id_hr references contact(id) > and the contact(type='t1') > and that id_wk references contact(id) and the contact(type='t2'). If I understand what you want, you can do this with a multi-column foreign key and check constraints. CREATE TABLE werke1 ( id SERIAL, id_hr NOT NULL, hr_contact NOT NULL CHECK (hr_contact = 't1'), id_wk int4 NOT NULL, wk_contact NOT NULL CHECK (hr_contact = 't2'), CONSTRAINT werke1_hr FOREIGN KEY (id_hr,hr_contact) references contact(id,type), CONSTRAINT werke1_wk FOREIGN KEY (id_wk, wk_contact) references contact(id,type) ); This will cause the FKEY to match only contact entries that have the correct combination of id and type. Hope that helps! > > More explicit: the id_hr shows to the id from contact, and this line from > contact must have the line type='t1'. The same for id_wk just the type is > another. > > I can write: > CREATE TABLE werke1( > id SERIAL, > id_hr int4 NOT NULL references contact(id), > id_wk int4 NOT NULL references contact(id) > ); > but how do I check also the type column? > > Best regards, > Andy. -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer http://open-ils.org -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer http://open-ils.org ---(end of broadcast)--- TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]
Re: [SQL] Serial and Index
On Sun, 27 Feb 2005 12:54:52 +, Sam Adams <[EMAIL PROTECTED]> wrote: > I read at http://jamesthornton.com/postgres/FAQ/faq-english.html#4.15.1 > that when a serial is created then an index is created on the column. > However I can't seem to find this anywhere in the PoistgreSQL manual. Is > this true? Thanks. The FAQ entry is incorrect. If you make your SERIAL column the PRIMARY KEY of the table, however, a UNIQUE index will be created. -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer http://open-ils.org ---(end of broadcast)--- TIP 5: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faq
Re: [SQL] detaching triggers
On Sun, 27 Mar 2005 17:41:02 +0200, Enrico Weigelt <[EMAIL PROTECTED]> wrote: > > Hi folks, > > is it somehow possible to detach trigger, so the calling transaction > can return immediately, even before the trigger function has > returned. No, but see below. > The only solution I currently know is to fill somethings in a queue > table by rule and have an external daemon looking at it every second. > But this doesnt seem very optimal for me. Take a look at the LISTEN/NOTIFY interfaces in the docs. This will allow async post-transaction processing. You can set up an ALSO rule to notify when a particular type of statement has executed against your target table. http://www.postgresql.org/docs/8.0/static/sql-listen.html http://www.postgresql.org/docs/8.0/static/sql-notify.html See the bottom of: http://www.postgresql.org/docs/8.0/static/sql-createrule.html Hope that helps! -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer http://open-ils.org ---(end of broadcast)--- TIP 6: Have you searched our list archives? http://archives.postgresql.org
Re: [SQL] gone blind - can't see syntax error
On Apr 1, 2005 11:36 AM, Gary Stainburn <[EMAIL PROTECTED]> wrote: > Hi folks. > > I've been looking at this for 10 minutes and can't see what's wrong. > Anyone care to enlighten me. > > Thanks > > Gary > > [EMAIL PROTECTED] webroot]# psql -a -f new-view.sql > SELECT r.r_id, r.r_registration, r.r_chassis, r.r_vehicle, r.r_fuel, > r.r_pack_mats, r.r_delivery, > (date(r.r_delivery) - date(now())) AS r_remaining, r.r_created, > r.r_completed, r.r_salesman, > sm.r_salesman as salesman_name, > d.d_des, de.de_des, > u.u_id, u.u_userid, u.u_username, u.u_salesman, u.u_target, > t.t_id, t.t_des, > s.s_id, s.s_des, > c.c_id, c.c_des, > co.com_count, co.com_unseen > FROM requests r, ^^^ > left outer join users sm on sm.u_id = r.r_salesman, > left outer join users u on r.r_u_id = u.u_id, > left outer join request_types t on r.r_t_id = t.t_id, > left outer join request_states s on r.r_s_id = s.s_id, > left outer join dealerships d on r.r_d_id = d.d_id, > left outer join departments de on r.r_de_id = de.de_id, > left outer join customers c on r.r_c_id = c.c_id, > left outer join comment_tallies co on r.r_id = co.r_id > ORDER BY r.r_id; > psql:new-view.sql:19: ERROR: parser: parse error at or near "left" Don't put commas between your joins. -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer http://open-ils.org ---(end of broadcast)--- TIP 4: Don't 'kill -9' the postmaster
Re: [SQL] Speed up slow select - was gone blind
Can you send the EXPLAIN ANALYZE of each? We can't really tell where the slowdown is without that. On Apr 1, 2005 12:32 PM, Gary Stainburn <[EMAIL PROTECTED]> wrote: > Hi folks. > > I've got my select working now, but I haven't received the speed > increase I'd expected. It replaced an earlier select which combined a > single explicit join with multiple froms. > > The first select is the old one, the second one is the new one (with a > new join). The new one takes 24 seconds to run while the old one took > 29. > > How can I redo the select to improve the speed, or what else can I do to > optimaise the database? > > original (ugly) > ~ > > SELECT r.r_id, r.r_registration, r.r_chassis, r.r_vehicle, r.r_fuel, > r.r_pack_mats, r.r_delivery, > (date(r.r_delivery) - date(now())) AS r_remaining, > r.r_created, r.r_completed, r.r_salesman, r.salesman_name, > d.d_des, de.de_des, > u.u_id, u.u_userid, u.u_username, u.u_salesman, u.u_target, > t.t_id, t.t_des, > s.s_id, s.s_des, > c.c_id, c.c_des, > co.com_count, co.com_unseen > FROM (SELECT r.r_id, r.r_t_id, r.r_d_id, r.r_de_id, r.r_s_id, > r.r_registration, r.r_chassis, r.r_c_id, r.r_vehicle, > r.r_fuel, r.r_pack_mats, r.r_delivery, r.r_salesman, > r.r_created, r.r_completed, r.r_u_id, > u.u_username AS salesman_name > FROM (requests r LEFT JOIN users u ON > ((r.r_salesman = u.u_id r, > users u, > request_types t, > request_states s, > dealerships d, > departments de, > customers c, > comment_tallies co > WHERE (r.r_d_id = d.d_id) AND > (r.r_s_id = s.s_id) AND > (r.r_c_id = c.c_id) AND > (r.r_t_id = t.t_id) AND > (r.r_d_id = d.d_id) AND > (r.r_de_id = de.de_id) AND > (r.r_u_id = u.u_id) AND > (r.r_id = co.r_id)) > ORDER BY r.r_id; > > new > ~~~ > SELECT r.r_id, r.r_registration, r.r_chassis, r.r_vehicle, r.r_fuel, > r.r_pack_mats, r.r_delivery, > (date(r.r_delivery) - date(now())) AS r_remaining, r.r_created, > r.r_completed, r.r_salesman, > sm.u_username as salesman_name, > d.d_des, de.de_des, > u.u_id, u.u_userid, u.u_username, u.u_salesman, u.u_target, > t.t_id, t.t_des, > s.s_id, s.s_des, > c.c_id, c.c_des, > co.com_count, co.com_unseen, > pl.pl_id, pl.pl_desc as plates > FROM requests r > left outer join users sm on sm.u_id = r.r_salesman > left outer join users u on r.r_u_id = u.u_id > left outer join request_types t on r.r_t_id = t.t_id > left outer join request_states s on r.r_s_id = s.s_id > left outer join dealerships d on r.r_d_id = d.d_id > left outer join departments de on r.r_de_id = de.de_id > left outer join customers c on r.r_c_id = c.c_id > left outer join comment_tallies co on r.r_id = co.r_id > left outer join plates pl on r.r_plates = pl.pl_id > ORDER BY r.r_id; > > -- > Gary Stainburn > > This email does not contain private or confidential material as it > may be snooped on by interested government parties for unknown > and undisclosed purposes - Regulation of Investigatory Powers Act, 2000 > > ---(end of broadcast)--- > TIP 9: the planner will ignore your desire to choose an index scan if your > joining column's datatypes do not match > -- Mike Rylander [EMAIL PROTECTED] GPLS -- PINES Development Database Developer http://open-ils.org ---(end of broadcast)--- TIP 7: don't forget to increase your free space map settings
Re: [SQL] ENUM like data type
On 6/21/05, MRB <[EMAIL PROTECTED]> wrote:
> Hi All,
>
> I have something in mind I'm not certain is do-able.
>
> I'm working with a lot of data from MySQL where the MySQL ENUM type is used.
>
MySQL's ENUM is basically a wrapper for CHECK. You can use a CHECK
constraint like this:
CREATE TABLE test(
testfield TEXT CHECK (testfield IN( 'Bits', 'of', 'data'))
);
> This is not a big problem per se but creating the proper lookup tables
> is becoming a bit tedious so I was hoping to make something better of it.
>
> Here is where I get uncertain as to if this is possible. My idea is to
> create a pseudo type that triggers the creation of it's lookup tables
> the same way the SERIAL type triggers creation of a sequence and returns
> an int with the right default value.
Although you can't create a generic type to handle this, you can
create a DOMAIN to wrap up your constraint for each "enum" type field
that you want:
CREATE DOMAIN fruit AS TEXT CHECK (VALUE IN ('apple','orange','banana'));
CREATE TABLE eat (
food fruit
);
http://www.postgresql.org/docs/8.0/interactive/sql-createdomain.html
Hope that helps.
--
Mike Rylander
[EMAIL PROTECTED]
GPLS -- PINES Development
Database Developer
http://open-ils.org
---(end of broadcast)---
TIP 6: Have you searched our list archives?
http://archives.postgresql.org
