Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PostgreSql] znak ' w stringu

665 views
Skip to first unread message

Tomasz

unread,
Jan 11, 2014, 6:55:25 AM1/11/14
to
Poradzcie mi jak w pl/pgsql wpisac do stringu ograniczonego przeciez znakami
' rowniez taki sam znak '

Wojtek Gapiński

unread,
Jan 11, 2014, 8:30:25 AM1/11/14
to
Dnia 11-01-2014 12:55 Tomasz napisał:
> Poradzcie mi jak w pl/pgsql wpisac do stringu ograniczonego przeciez
> znakami ' rowniez taki sam znak '

Nie znam pg, ale znak ucieczki (\) nie działa?

--
Wojtek Gapiński
http://jwmprojekt.pl

hubert depesz lubaczewski

unread,
Jan 11, 2014, 9:16:31 AM1/11/14
to
On 2014-01-11, Tomasz <tutom...@gmail.com> wrote:
> Poradzcie mi jak w pl/pgsql wpisac do stringu ograniczonego przeciez znakami
> ' rowniez taki sam znak '

''
(dwa apostrofy)
albo, naucz się korzystać z $stringow$.

np.
create function x () returns int4 as $depesz$
begin
return '123'::int4 + 456;
end;
$depesz$ language plpgsql;

Dowolny string możesz wrzucić między parę wyrażeń $cokolwiek$
W szczególności - cokolwiek może być puste, i wtedy używasz $$

depesz

--
The best thing about modern society is how easy it is to avoid contact with it.
http://depesz.com/

Tomasz

unread,
Jan 11, 2014, 9:23:36 AM1/11/14
to

Użytkownik "Wojtek Gapiński" <wojtas_g....@wp.I.TO.TEZ.pl> napisał
>
> Nie znam pg, ale znak ucieczki (\) nie działa?
>
W prostym selekcie np. select '\'tekst\'';
to dziala dobrze ale w procedurze skladowanej musze miec cos takiego:
EXECUTE 'select nextval(' || tablename || ')' into retval;
gdzie tablename = 's_mahnung_gruppe', a tu niestety nie potrafie sobie
poradzic,
jesli wstawie \' to system traktuje to jako poczatek nastepnego stringu.

ponizszy zapis dziala poprawnie ale nazwa tabeli jest na sztywno a ja chce
ja brac z parametru.
-- select nextval('s_mahnung_gruppe') into retval;





hubert depesz lubaczewski

unread,
Jan 11, 2014, 9:22:15 AM1/11/14
to
On 2014-01-11, Wojtek Gapiński <wojtas_g....@wp.I.TO.TEZ.pl> wrote:
> Dnia 11-01-2014 12:55 Tomasz napisał:
>> Poradzcie mi jak w pl/pgsql wpisac do stringu ograniczonego przeciez
>> znakami ' rowniez taki sam znak '
> Nie znam pg, ale znak ucieczki (\) nie działa?

I tak i nie. Jak masz prawidłowo skonfigurowanego Pg, nowego, to nie
zadziała:

#v+
$ select 'a\'b';
>>
#v-

(>> znaczy, że czeka na ciąg dalszy polecenia).

Albo, wywali warninga:

#v+
$ select 'a\'b';
WARNING: nonstandard use of \' in a string literal
LINE 1: select 'a\'b';
^
HINT: Use '' to write quotes in strings, or use the escape string syntax (E'...').
?column?
----------
a'b
(1 row)
#v-

To dlatego, że *standard SQL* nie przewiduje escape'owania backslashem w
normalnych stringach.
Większość baz to implementuje, ale Pg (a przynajmniej od pewnego czasu)
stara się mocno być bardzo zgodny ze standardem, i najpierw generował
warninga, a teraz odrzuca.
Oczywiście - da się to wyłączyć opcjami, ale po co kombinować, skoro:
1. możesz użyć E'' stringów, które mają backslash-escape:
#v+
$ select E'a\'b';
?column?
----------
a'b
(1 row)
#v-

2. lepiej i tak użyć dolar-quotes:
#v+
$ select $$a'b$$;
?column?
----------
a'b
(1 row)
#v-

A z zupełnie innej beczki - jeśli programista, piszący zapytania do bazy
danych, z poziomu jakiegoś języka programowania (a nie np. z poziomu psql'a)
używa znaku ' - to na 99.9% popełnia błąd (a przynajmniej generuje coś co
niektórzy określają jako "code smell").

Tomasz

unread,
Jan 12, 2014, 5:32:12 AM1/12/14
to

Użytkownik "hubert depesz lubaczewski" <dep...@depesz.com> napisał

> albo, naucz się korzystać z $stringow$.
>
> np.
> create function x () returns int4 as $depesz$
> begin
> return '123'::int4 + 456;
> end;
> $depesz$ language plpgsql;
>
> Dowolny string możesz wrzucić między parę wyrażeń $cokolwiek$
> W szczególności - cokolwiek może być puste, i wtedy używasz $$

Nie bardzo zrozumialem do czego miala sluzyc Twoja przykladowa funkcja.
Zwraca ona po prosu sume dwoch liczb typu integer.
--
Tomasz

Tomasz

unread,
Jan 12, 2014, 6:54:34 AM1/12/14
to

Użytkownik "hubert depesz lubaczewski" <dep...@depesz.com> napisał

> (dwa apostrofy)
> albo, naucz się korzystać z $stringow$.
>
Przepraszam za zamieszanie ale juz sobie poradzilem przy pomocy chr(39):

EXECUTE 'select nextval ('|| chr(39) || tablename || chr(39)|| ')' into
retval;

juz wszystko dziala poprawnie.

--
Tomasz

artiun

unread,
Jan 12, 2014, 9:44:33 AM1/12/14
to
W dniu 2014-01-12 12:54, Tomasz pisze:
OK, ale to jest chore.


--
Artur
0 weeks 4 days 7 hours 34 minutes 23 seconds and 173 milliseconds.
"pl.comp.bazy-danych"

Tomasz

unread,
Jan 12, 2014, 10:35:03 AM1/12/14
to

Użytkownik "artiun" <art...@spam.wp.pl> napisał

>> EXECUTE 'select nextval ('|| chr(39) || tablename || chr(39)|| ')' into
>> retval;
>>
>> juz wszystko dziala poprawnie.
>>
> OK, ale to jest chore.

Jesli to jest chore, to bardzo bym prosil o podanie jak zdrowiej napisac ta
instrukcje:
EXECUTE 'select nextval ('|| chr(39) || tablename || chr(39)|| ')' into
retval;
przeciez po to pytalem na tej grupie.

--
Tomasz

hubert depesz lubaczewski

unread,
Jan 13, 2014, 9:20:41 AM1/13/14
to
bo jest *przykładowa*. ma pokazać jak używać $quotes$.

hubert depesz lubaczewski

unread,
Jan 13, 2014, 9:20:20 AM1/13/14
to
On 2014-01-12, Tomasz <tutom...@gmail.com> wrote:
> Jesli to jest chore, to bardzo bym prosil o podanie jak zdrowiej napisac ta
> instrukcje:
> EXECUTE 'select nextval ('|| chr(39) || tablename || chr(39)|| ')' into
> retval;
> przeciez po to pytalem na tej grupie.


Nie o to pytałeś, tylko o quotowanie.
a to co napisałeś jest chore i błędne.

Czemu nie użyjesz po prostu:
retval := nextval( tablename );

Tomasz

unread,
Jan 13, 2014, 1:13:15 PM1/13/14
to

Użytkownik "hubert depesz lubaczewski" <dep...@depesz.com> napisał

> a to co napisałeś jest chore i błędne.
>
> Czemu nie użyjesz po prostu:
> retval := nextval( tablename );
>
Bo tablename jest nazwą parametru funkcji.
Funkcja zwraca nextval dla dowolnej, przekazanej przez parametr tabeli.
Mam w bazie 63 sekwencje i nie bede przeciez robil 63 funkcyjek aby pobrac
z nich nextval.
Jak bys Ty to zrobil bardziej zdrowo, być może można inaczej ale ja nie znam
innej metody niż poprzez EXECUTE.

--
Tomasz

hubert depesz lubaczewski

unread,
Jan 14, 2014, 7:15:25 AM1/14/14
to
On 2014-01-13, Tomasz <tutom...@gmail.com> wrote:
>> Czemu nie użyjesz po prostu:
>> retval := nextval( tablename );
> Bo tablename jest nazwą parametru funkcji.

A co to ma do rzeczy?

> Funkcja zwraca nextval dla dowolnej, przekazanej przez parametr tabeli.
> Mam w bazie 63 sekwencje i nie bede przeciez robil 63 funkcyjek aby pobrac
> z nich nextval.

Nie wiem co chcesz uzyskać, ale wygląda to na "ogólną funkcję
wstawiającą dane do dowolnej tabeli i pobierającą id wstawionego
rekordu".
Jeśli tak, to czemu po prostu nie użyjesz "insert"?

> Jak bys Ty to zrobil bardziej zdrowo, być może można inaczej ale ja nie znam
> innej metody niż poprzez EXECUTE.

*dokładnie* tak jak napisałem.
Czy chociażby spróbowałeś?

(tak, wiem, że nie spróbowałeś).

Tomasz

unread,
Jan 14, 2014, 8:56:53 AM1/14/14
to

Użytkownik "hubert depesz lubaczewski" <dep...@depesz.com> napisał
>
> *dokładnie* tak jak napisałem.
> Czy chociażby spróbowałeś?
>
> (tak, wiem, że nie spróbowałeś).
>
Widze ze Ty zupelnie nie zrozumiales o czym ja pisze.
Tu nie chodzi o zwykla tabele tylko sekwencje.
Dla przykladu podaje skrypt Create jednej z sekwencji:

CREATE SEQUENCE s_inart
INCREMENT 1
MINVALUE 1
MAXVALUE 999999999999
START 1
CACHE 1;
ALTER TABLE s_inart
OWNER TO autohaus;

Sekwencja nie jest zwykla tabela i jej obsluga jest tez zupelnie inna.
Aby pobrac z niej nastepny numer z jednoczesnym zwiekszenia o 1 nalezy uzyc
takiej instrukcji jak napisalem :
select nextval('s_inart');
Każde uruchomienie tego selekta zwieksza sekwencje o 1.

--
Tomasz

Ronald Kuczek

unread,
Jan 14, 2014, 10:33:22 AM1/14/14
to
Zbuduj zapytanie dynamicznie:

create or replace function get_nextval_of_sequence(text) returns int8 as
$BODY$
declare res int8;
query text;
begin
query:='select nextval('||''''||$1||''''||')';
execute query into res;
return res;
end;
$BODY$
LANGUAGE plpgsql;

no i odpytaj:

select get_nextval_of_sequence('s_inart');

Pozdrawiam
Rony

Ronald Kuczek

unread,
Jan 14, 2014, 10:41:05 AM1/14/14
to
Tudzież Twoje pierwotne

execute get_nextval_of_sequence(nazwatabeli) into retval;

Pozdrawiam
Rony

Lesiok

unread,
Jan 14, 2014, 12:07:17 PM1/14/14
to
On 14.01.14 16:33, Ronald Kuczek wrote:
> Zbuduj zapytanie dynamicznie:
>
> create or replace function get_nextval_of_sequence(text) returns int8 as
> $BODY$
> declare res int8;
> query text;
> begin
> query:='select nextval('||''''||$1||''''||')';
> execute query into res;
> return res;
> end;
> $BODY$
> LANGUAGE plpgsql;
>
> no i odpytaj:
>
> select get_nextval_of_sequence('s_inart');
>
> Pozdrawiam
> Rony

Ale po co ?????

Przecie� taka konstrukcja normalnie dzia�a :

CREATE OR REPLACE FUNCTION get_nextval_of_sequence(text)
RETURNS bigint AS
$BODY$
DECLARE
declare res int8 := 0;
BEGIN
SELECT INTO res nextval($1);
RETURN res;
END
$BODY$
LANGUAGE plpgsql;

W przeciwie�stwie do za�o�yciela w�tku sprawdzi�em r�wnie� organoleptycznie.
--
================================
Leszek KUBRAK

Tomasz

unread,
Jan 14, 2014, 12:40:37 PM1/14/14
to

U�ytkownik "Lesiok" <les...@infokub.com.pl> napisa� w wiadomo�ci
news:52d56ec5$0$2222$6578...@news.neostrada.pl...
Faktycznie Twoja funkcja dziala, sprawdzi�em, ale przeciez ju� 12 stycznia
pisalem ze moja funkcja dziala poprawnie i podalem jej najwaznieszy
fragment. Cala funkcja, uzywana od paru dni wyglada tak:

CREATE OR REPLACE FUNCTION fun_get_next_value_from_sequence(tablename
character varying)
RETURNS integer AS
$BODY$
DECLARE
retval integer=0;
BEGIN
EXECUTE 'select nextval ('|| chr(39) || tablename || chr(39)|| ')' into
retval;
return retval;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;

Dzieki waszym odpowiedziom pozna�em juz trzy rozne metody rozwiazania tego
samego problemu. Nauki nigdy za wiele.

--
Tomasz

hubert depesz lubaczewski

unread,
Jan 14, 2014, 12:39:26 PM1/14/14
to
On 2014-01-14, Ronald Kuczek <kuc...@kuczek.pl> wrote:
> Zbuduj zapytanie dynamicznie:
>
> create or replace function get_nextval_of_sequence(text) returns int8 as
> $BODY$
> declare res int8;
> query text;
> begin
> query:='select nextval('||''''||$1||''''||')';
> execute query into res;
> return res;
> end;
> $BODY$
> LANGUAGE plpgsql;
>
> no i odpytaj:
> select get_nextval_of_sequence('s_inart');

AAAAArgh. Ale po co?
Zwykłe:
res := nextval( $1 );
zadziała całkowicie poprawnie.
Można ewentualnie casta na regclass dorzucić.

hubert depesz lubaczewski

unread,
Jan 14, 2014, 12:41:14 PM1/14/14
to
On 2014-01-14, Tomasz <tutom...@gmail.com> wrote:
>
> CREATE SEQUENCE s_inart
> INCREMENT 1
> MINVALUE 1
> MAXVALUE 999999999999
> START 1
> CACHE 1;
> ALTER TABLE s_inart
> OWNER TO autohaus;
>
> Sekwencja nie jest zwykla tabela i jej obsluga jest tez zupelnie inna.
> Aby pobrac z niej nastepny numer z jednoczesnym zwiekszenia o 1 nalezy uzyc
> takiej instrukcji jak napisalem :
> select nextval('s_inart');
> Każde uruchomienie tego selekta zwieksza sekwencje o 1.

Może to jest szokujące, ale wiem co to jest sekwencja.
Nie wiem jaki masz problem z kodem który podałem.
Jeśli w zmiennej "xxx" masz nazwę sekwencji, to w funkcji plpgsql kod

cokolwiek := nextval( xxx );
wstawi do cokolwiek wartość z sekwencji, i dodatkowo zwiekszy ją
o jeden. Tak jak już pisałem.

hubert depesz lubaczewski

unread,
Jan 14, 2014, 3:48:14 PM1/14/14
to
On 2014-01-14, Tomasz <tutom...@gmail.com> wrote:
> Faktycznie Twoja funkcja dziala, sprawdziłem, ale przeciez już 12 stycznia
> pisalem ze moja funkcja dziala poprawnie i podalem jej najwaznieszy
> fragment. Cala funkcja, uzywana od paru dni wyglada tak:
>
> CREATE OR REPLACE FUNCTION fun_get_next_value_from_sequence(tablename
> character varying)
> RETURNS integer AS
> $BODY$
> DECLARE
> retval integer=0;
> BEGIN
> EXECUTE 'select nextval ('|| chr(39) || tablename || chr(39)|| ')' into
> retval;
> return retval;
> END;
> $BODY$
> LANGUAGE plpgsql VOLATILE;
>
> Dzieki waszym odpowiedziom poznałem juz trzy rozne metody rozwiazania tego
> samego problemu. Nauki nigdy za wiele.

I parę osób napisało, że to nie ma sensu.
Podane przez Ciebie rozwiązanie jest:
- wolne
- niebezpieczne (co jeśli tablename zawiera spację?)
- mało funkcjonalne (co jeśli będziesz chciał użyć schemy której nie ma
w search_path?

Dodatkowo - po co to w ogóle jest - tak jak pokazałeś twoja funkcja
fun_get_next_value_from_sequence() nie robi niczego czego nexval() sam
z siebie nie potrafi, a dodatkowo nextval jest szybszy.

Tomasz

unread,
Jan 14, 2014, 4:15:19 PM1/14/14
to

Użytkownik "hubert depesz lubaczewski" <dep...@depesz.com> napisał
>
> Dodatkowo - po co to w ogóle jest - tak jak pokazałeś twoja funkcja
> fun_get_next_value_from_sequence() nie robi niczego czego nexval() sam
> z siebie nie potrafi, a dodatkowo nextval jest szybszy.

Tylko ze ja tą funkcje wywoluje nie z poziomu bazy danych a z poziomu Javy.
Z poziomu Javy jest mi wygodniej uzyc funkcji bazodanowej ponieważ od lat
mam już wyprobowane narzedzia do takiej komunikacji i nie chce mi sie
szukać nowych rozwiazań.

--
Tomasz

R.e.m.e.K

unread,
Jan 14, 2014, 4:23:00 PM1/14/14
to
Dnia Tue, 14 Jan 2014 22:15:19 +0100, Tomasz napisał(a):

> Nauki nigdy za wiele.

> nie chce mi sie szukać nowych rozwiazań.

Te dwa zdania stoja w jawnym konflikcie

--
pozdro
R.e.m.e.K

Tomasz

unread,
Jan 14, 2014, 4:50:13 PM1/14/14
to

Użytkownik "R.e.m.e.K" <g...@dev.null> napisał

>> Nauki nigdy za wiele.
>
>> nie chce mi sie szukać nowych rozwiazań.
>
> Te dwa zdania stoja w jawnym konflikcie
>
W tym drugim przypadku wyrazilem sie niezbyt precyzyjnie, powinno być:
" ... nie chce mi sie szukać nowych rozwiazań skoro istniejace spełniaja
swoje zadania."

--
Tomasz

hubert depesz lubaczewski

unread,
Jan 14, 2014, 4:36:44 PM1/14/14
to
On 2014-01-14, Tomasz <tutom...@gmail.com> wrote:
>
A jaka jest w związku z tym różnica między
fun_get_next_value_from_sequence a nextval?
obie to funkcje.?
Chcesz użyć funkcji, więc obudowałeś *funkcję* własną *funkcją*, która
niczego nie dokłada, poza dodatkowym czasem do wykonania.

Ronald Kuczek

unread,
Jan 14, 2014, 4:51:04 PM1/14/14
to
W dniu 14.01.2014 18:39, hubert depesz lubaczewski pisze:
>
> AAAAArgh. Ale po co?
> Zwykłe:
> res := nextval( $1 );
> zadziała całkowicie poprawnie.
> Można ewentualnie casta na regclass dorzucić.
> depesz
>

No cóż, kolega chciał mieć ' w stringu ? No to niech ma.
Pewnie, że nextval ($1) zadziała ale znów dostałbym ripostę, że nie o to
chodziło. Zdążyłem się nauczyć, że w pewnych sytuacjach trzeba podać
rozwiązanie, choćby nieoptymalne ale zgodne z koncepcją pytającego,
inaczej napotykasz na mur niezrozumienia. Zresztą wątek też zaczął się
od pytania "jak umieścić znak ' w stringu" zamiast "jak dynamicznie
odpytać sekwencję, której nazwa jest przekazywana jako parametr do
funkcji. N postów dalej i n czasu dopiero dochodzimy do sedna.
Dokładne określenie problemu to też sztuka.

Pozdrawiam
Rony

R.e.m.e.K

unread,
Jan 14, 2014, 5:04:56 PM1/14/14
to
Dnia Tue, 14 Jan 2014 22:51:04 +0100, Ronald Kuczek napisał(a):

> Dokładne określenie problemu to też sztuka.

+10

--
pozdro
R.e.m.e.K

Ronald Kuczek

unread,
Jan 15, 2014, 8:11:25 AM1/15/14
to
A jaki problem z bezpośrednim wywołaniem nextval z poziomu Javy ?

Connection conn = //tutaj twoje połączenie;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select nextval('"+
Twoja_zmienna_z_nazwa_sekwencji + "')");
rs.next();
Integer nextVal = new Integer(rs.getString(1));
//no i masz wartość z którą robisz co zechcesz
//bez tworzenia dodatkowych funkcji w plpgsql


Pozdrawiam
Rony

Tomasz

unread,
Jan 15, 2014, 12:32:04 PM1/15/14
to

Użytkownik "Ronald Kuczek" <kuc...@kuczek.pl> napisał
>
> A jaki problem z bezpośrednim wywołaniem nextval z poziomu Javy ?
>
> Connection conn = //tutaj twoje połączenie;
> Statement stmt = conn.createStatement();
> ResultSet rs = stmt.executeQuery("select nextval('"+
> Twoja_zmienna_z_nazwa_sekwencji + "')");
> rs.next();
> Integer nextVal = new Integer(rs.getString(1));
> //no i masz wartość z którą robisz co zechcesz
> //bez tworzenia dodatkowych funkcji w plpgsql

Dzieki za gotowy przyklad.
Wczoraj po sugestii depesza zrobilem cos podobnego i tez dziala.

--
Tomasz

0 new messages