Setting an auto increment value - postgresql

If I have schemas SCHEMA1 with tables tbl_one and tbl_two, SCHEMA2 with table tbl_tree,
how to use in PostgreSQL command setval():
SELECT SETVAL('SCHEMA1.tbl_one_id_seq', 234) FROM SCHEMA1.tbl_one;
SELECT SETVAL('SCHEMA1.tbl_two_id_seq', 345) FROM SCHEMA1.tbl_two;
SELECT SETVAL('SCHEMA2.tbl_tree_id_seq', 456) FROM SCHEMA2.tbl_tree;
These don't work.

Try ALTER SEQUENCE SCHEMA1.tbl_one_id_seq RESTART WITH 234 and so forth.

You don't need the FROM clause. Just:
SELECT SETVAL('SCHEMA1.tbl_one_id_seq', 234);
In future, when you say "it doesn't work" you should be specific about what error message you get exactly.
Possibly your schema is case-perserved? If so, you want:
SELECT SETVAL('"SCHEMA1"."tbl_one_id_seq"', 234);
Note the quotes on the identifier to prevent case-folding.

Note the lower case spelling of 'schema1.tbl_one_id_seq'. Unless you double-quoted names when creating objects, you need to lower case the name here.
SELECT setval('schema1.tbl_one_id_seq', max(id))
FROM SCHEMA1.tbl_one -- case irrelevant while not double-quoted
Fetching the maximum id, btw - else you wouldn't need to select from the table.

Related

Timescaledb - How to display chunks of a hypertable in a specific schema

I have a table named conditions on a schema named test. I created a hypertable and inserted hundreds of rows.
When I run select show_chunks(), it works and displays chunks but I cannot use the table name as parameter as suggested in the manual. This does not work:
SELECT show_chunks("test"."conditions");
How can I fix this?
Ps: I want to query the chunk itself by its name? How can I do this?
The show_chunks expects a regclass, which depending on your current search path means you need to schema qualify the table.
The following should work:
SELECT public.show_chunks('test.conditions');
The double quotes are only necessary if your table is a delimited identifier, for example if your tablename contains a space, you would need to add the double quotes for the identifier. You will still need to wrap it in single quotes though:
SELECT public.show_chunks('test."equipment conditions"');
SELECT public.show_chunks('"test schema"."equipment conditions"');
For more information about identifier quoting:
https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
Edit: Addressing the PS:
I want to query the chunk itself by its name? How can I do this?
feike=# SELECT public.show_chunks('test.conditions');
show_chunks
--------------------------------------------
_timescaledb_internal._hyper_28_1176_chunk
_timescaledb_internal._hyper_28_1177_chunk
[...]
SELECT * FROM _timescaledb_internal._hyper_28_1176_chunk;

Postgres query for sequence containing camel case

I want to set a sequence in my table. So I listed all sequences with
SELECT c.relname
FROM pg_class c
WHERE c.relkind = 'S';
which gives me e.g.: tableName_id_seq
when I try to set the sequence using
SELECT setval("tableName_id_seq", (SELECT MAX(id) from "tableName"));
I get:
ERROR: relation "tableName_id_seq" does not exist
LINE 1: SELECT setval('tableName_id_seq', (SELECT MAX(id) from "t...
I already tried single and double quotes. Anyone any idea what to do here?
Avoid creating identifiers in camel case. It's really boring to work with it:
CREATE SEQUENCE "CamelCaseSeq";
SELECT nextval(format('%I', 'CamelCaseSeq'));
SELECT setval(format('%I', 'CamelCaseSeq'), 6666);
SELECT currval(format('%I', 'CamelCaseSeq'));
SELECT * FROM "CamelCaseSeq";
A quote from the docs:
Quoting an identifier also makes it case-sensitive, whereas unquoted
names are always folded to lower case. For example, the identifiers
FOO, foo, and "foo" are considered the same by PostgreSQL, but "Foo"
and "FOO" are different from these three and each other.
More info here and here.

Is name a special keyword in PostgreSQL?

I am using Ubuntu and PostgreSql 8.4.9.
Now, for any table in my database, if I do select table_name.name from table_name, it shows a result of concatenated columns for each row, although I don't have any name column in the table. For the tables which have name column, no issue. Any idea why?
My results are like this:
select taggings.name from taggings limit 3;
---------------------------------------------------------------
(1,4,84,,,PlantCategory,soil_pref_tags,"2010-03-18 00:37:55")
(2,5,84,,,PlantCategory,soil_pref_tags,"2010-03-18 00:37:55")
(3,6,84,,,PlantCategory,soil_pref_tags,"2010-03-18 00:37:55")
(3 rows)
select name from taggings limit 3;
ERROR: column "name" does not exist
LINE 1: select name from taggings limit 3;
This is a known confusing "feature" with a bit of history. Specifically, you could refer to tuples from the table as a whole with the table name, and then appending .name would invoke the name function on them (i.e. it would be interpreted as select name(t) from t).
At some point in the PostgreSQL 9 development, Istr this was cleaned up a bit. You can still do select t from t explicitly to get the rows-as-tuples effect, but you can't apply a function in the same way. So on PostgreSQL 8.4.9, this:
create table t(id serial primary key, value text not null);
insert into t(value) values('foo');
select t.name from t;
produces the bizarre:
name
---------
(1,foo)
(1 row)
but on 9.1.1 produces:
ERROR: column t.name does not exist
LINE 1: select t.name from t;
^
as you would expect.
So, to specifically answer your question: name is a standard type in PostgreSQL (used in the catalogue for table names etc) and also some standard functions to convert things to the name type. It's not actually reserved, just the objects that exist called that, plus some historical strange syntax, made things confusing; and this has been fixed by the developers in recent versions.
According to the PostgreSQL documentation, name is a "non-reserved" keyword in PostgreSQL, SQL:2003, SQL:1999, or SQL-92.
SQL distinguishes between reserved and non-reserved key words. According to the standard, reserved key words are the only real key words; they are never allowed as identifiers. Non-reserved key words only have a special meaning in particular contexts and can be used as identifiers in other contexts. Most non-reserved key words are actually the names of built-in tables and functions specified by SQL. The concept of non-reserved key words essentially only exists to declare that some predefined meaning is attached to a word in some contexts.
The suggested fix when using keywords is:
As a general rule, if you get spurious parser errors for commands that contain any of the listed key words as an identifier you should try to quote the identifier to see if the problem goes away.

How to make "case-insensitive" query in Postgresql?

Is there any way to write case-insensitive queries in PostgreSQL, E.g. I want that following 3 queries return same result.
SELECT id FROM groups where name='administrator'
SELECT id FROM groups where name='ADMINISTRATOR'
SELECT id FROM groups where name='Administrator'
Use LOWER function to convert the strings to lower case before comparing.
Try this:
SELECT id
FROM groups
WHERE LOWER(name)=LOWER('Administrator')
using ILIKE instead of LIKE
SELECT id FROM groups WHERE name ILIKE 'Administrator'
The most common approach is to either lowercase or uppercase the search string and the data. But there are two problems with that.
It works in English, but not in all languages. (Maybe not even in
most languages.) Not every lowercase letter has a corresponding
uppercase letter; not every uppercase letter has a corresponding
lowercase letter.
Using functions like lower() and upper() will give you a sequential
scan. It can't use indexes. On my test system, using lower() takes
about 2000 times longer than a query that can use an index. (Test data has a little over 100k rows.)
There are at least three less frequently used solutions that might be more effective.
Use the citext module, which mostly mimics the behavior of a case-insensitive data type. Having loaded that module, you can create a case-insensitive index by CREATE INDEX ON groups (name::citext);. (But see below.)
Use a case-insensitive collation. This is set when you initialize a
database. Using a case-insensitive collation means you can accept
just about any format from client code, and you'll still return
useful results. (It also means you can't do case-sensitive queries. Duh.)
Create a functional index. Create a lowercase index by using CREATE
INDEX ON groups (LOWER(name));. Having done that, you can take advantage
of the index with queries like SELECT id FROM groups WHERE LOWER(name) = LOWER('ADMINISTRATOR');, or SELECT id FROM groups WHERE LOWER(name) = 'administrator'; You have to remember to use LOWER(), though.
The citext module doesn't provide a true case-insensitive data type. Instead, it behaves as if each string were lowercased. That is, it behaves as if you had called lower() on each string, as in number 3 above. The advantage is that programmers don't have to remember to lowercase strings. But you need to read the sections "String Comparison Behavior" and "Limitations" in the docs before you decide to use citext.
You can use ILIKE. i.e.
SELECT id FROM groups where name ILIKE 'administrator'
You can also read up on the ILIKE keyword. It can be quite useful at times, albeit it does not conform to the SQL standard. See here for more information: http://www.postgresql.org/docs/9.2/static/functions-matching.html
You could also use POSIX regular expressions, like
SELECT id FROM groups where name ~* 'administrator'
SELECT 'asd' ~* 'AsD' returns t
use ILIKE
select id from groups where name ILIKE 'adminstration';
If your coming the expressjs background and name is a variable
use
select id from groups where name ILIKE $1;
Using ~* can improve greatly on performance, with functionality of INSTR.
SELECT id FROM groups WHERE name ~* 'adm'
return rows with name that contains OR equals to 'adm'.
ILIKE work in this case:
SELECT id
FROM groups
WHERE name ILIKE 'Administrator'
For a case-insensitive parameterized query, you can use the following syntax:
"select * from article where upper(content) LIKE upper('%' || $1 || '%')"
-- Install 'Case Ignore Test Extension'
create extension citext;
-- Make a request
select 'Thomas'::citext in ('thomas', 'tiago');
select name from users where name::citext in ('thomas', 'tiago');
If you want not only upper/lower case but also diacritics, you can implement your own func:
CREATE EXTENSION unaccent;
CREATE OR REPLACE FUNCTION lower_unaccent(input text)
RETURNS text
LANGUAGE plpgsql
AS $function$
BEGIN
return lower(unaccent(input));
END;
$function$;
Call is then
select lower_unaccent('Hôtel')
>> 'hotel'
A tested approach is using ~*
As in the example below
SELECT id FROM groups WHERE name ~* 'administrator'
select id from groups where name in ('administrator', 'ADMINISTRATOR', 'Administrator')

Omitting the double quote to do query on PostgreSQL

Simple question, is there any way to omit the double quote in PostgreSQL?
Here is an example, giving select * from A;, I will retrieve ERROR: relation "a" does not exist, and I would have to give select * from "A"; to get the real result.
Is there any way not to do the second and instead do the first on PostgreSQL?
Your problem with this query started when you created your table. When you create your table, don't use quotes.
Use this:
CREATE TABLE a ( ... );
Not this:
CREATE TABLE "A" ( ... );
The latter will make it so that you always have to quote it later. The former makes it a normal name and you can use SELECT * FROM a; or SELECT * FROM A;
If you can't just recreate your table, use the ALTER TABLE syntax:
ALTER TABLE "A" RENAME TO a;
double quotes are required if you include capital letters in your table name in postgres
to avoid the requirements name your table "a"
Postgresql has some particular behaviour in regard to quoting and case sentivity: it folds every non-quoted identifier to lower case (also at creation time) and then works case-sensitively.
Double quotes in identifiers are only needed when the identifier (table name, column name, etc) was defined (at schema creation time) with uppercase letters (some or all) and between double quotes.
In that case (which I advice against), when you use that identifier, you must type it in the same way: case sensitively (type upper/lower case letter exactly as defined) and between double quotes.
In other cases, you can use non-quoted identifiers and work always case-insensitively.
Don't use upper case letter in your table name or it's column name, if you are using such thing then the postgres will required double quote for accessing it.
Please see the detailed description of what is happening here.
The PostgreSQL server table names are case-sensitive, but forced to be lower-case by default: when you type CREATE TABLE AAA, it will become CREATE TABLE aaa before the query execution.
Double-quoted names keep their case as it was, so after CREATE TABLE "AaA" you get the table AaA and have to write it double-quoted again and again.
Have no idea why did they do so :)