Import CSV text array into PostgreSQL 9.2 - postgresql

I have data something like this:
Akhoond,1,Akhoond,"{""Akhund"", ""Akhwan""}",0
pgAdmin's import is rejecting this. What format does the text[] need to be in the CSV?
I also tried this:
Akhoond,1,Akhoond,"{Akhund, Akhwan}",0
Here's the table create:
CREATE TABLE private."Titles"
(
"Abbrev" text NOT NULL,
"LangID" smallint NOT NULL REFERENCES private."Languages" ("LangID"),
"Full" text NOT NULL,
"Alt" text[],
"Affix" bit
)
WITH (
OIDS=FALSE
);
ALTER TABLE private."Titles" ADD PRIMARY KEY ("Abbrev", "LangID");
CREATE INDEX ix_titles_alt ON private."Titles" USING GIN ("Alt");
ALTER TABLE private."Titles"
OWNER TO postgres;

The best way to find out is to create a table with the desired values and COPY ... TO STDOUT to see:
craig=> CREATE TABLE copyarray(a text, b integer, c text[], d integer);
CREATE TABLE
craig=> insert into copyarray(a,b,c,d) values ('Akhoond',1,ARRAY['Akhund','Akhwan'],0);
INSERT 0 1
craig=> insert into copyarray(a,b,c,d) values ('Akhoond',1,ARRAY['blah with spaces','blah,with,commas''and"quotes'],0);
INSERT 0 1
craig=> \copy copyarray TO stdout WITH (FORMAT CSV)
Akhoond,1,"{Akhund,Akhwan}",0
Akhoond,1,"{""blah with spaces"",""blah,with,commas'and\""quotes""}",0
So it looks like "{Akhund,Akhwan}" is fine. Note the second example I added showing how to handle commas, quotes spaces in the array text.
This works with the psql \copy command; if it doesn't work with PgAdmin-III then I'd suggest using psql and \copy.

Related

How to change a default separator for postgresql arrays?

I want to import csv with Postgres' arrays into a Postgres table.
This is my table:
create table dbo.countries (
id char(2) primary key,
name text not null,
elements text[]
CONSTRAINT const_dbo_countries_unique1 unique (id),
CONSTRAINT const_dbo_countries_unique2 unique (name)
);
and I want to insert into that a csv which looks like this:
AC,ac,{xx yy}
When I type copy dbo.mytable FROM '/home/file.csv' delimiter ',' csv; then the array is read as a one string: {"xx yy"}.
How to change a deafault separator for arrays from , to ?
You cannot to change array's separator symbol. You can read data to table, and later you can run a update on this table:
UPDATE dbo.countries
SET elements = string_to_array(elements[1], ' ')
WHERE strpos(elements[1], ' ') > 0;

Postgres 9.5 CREATE TABLE LIKE INCLUDING ALL NO FK Constraints? [duplicate]

Foreign key constraints are not copied when using
create table table_name ( like source_table INCLUDING ALL)'
in Postgres. How can I create a copy of an existing table including all foreign keys.
There is no option to automatically create foreign keys in CREATE TABLE ... LIKE ....
For the documentation:
LIKE source_table [ like_option ... ]
Not-null constraints are always copied to the new table. CHECK
constraints will be copied only if INCLUDING CONSTRAINTS is specified [...]
Indexes, PRIMARY KEY, and UNIQUE constraints on the original table
will be created on the new table only if the INCLUDING INDEXES clause
is specified.
In practice it's easy with GUI tools. For example, in PgAdmin III:
copy declaration (DDL) of source_table to query tool (ctrl-e),
edit the declaration,
execute sql.
In an SQL script you can use the following function. Important assumption: source table foreign keys have correct names i.e. their names contain source table name (what is a typical situation).
create or replace function create_table_like(source_table text, new_table text)
returns void language plpgsql
as $$
declare
rec record;
begin
execute format(
'create table %s (like %s including all)',
new_table, source_table);
for rec in
select oid, conname
from pg_constraint
where contype = 'f'
and conrelid = source_table::regclass
loop
execute format(
'alter table %s add constraint %s %s',
new_table,
replace(rec.conname, source_table, new_table),
pg_get_constraintdef(rec.oid));
end loop;
end $$;
Example of use:
create table base_table (base_id int primary key);
create table source_table (id int primary key, base_id int references base_table);
select create_table_like('source_table', 'new_table');
\d new_table
Table "public.new_table"
Column | Type | Modifiers
---------+---------+-----------
id | integer | not null
base_id | integer |
Indexes:
"new_table_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"new_table_base_id_fkey" FOREIGN KEY (base_id) REFERENCES base_table(base_id)
One more way is to dump the table structure, change it's name in dump, and load it again:
pg_dump -s -t old databases | sed 's/old/new/g' | psql

access postgres field given field name as text string

I have a table in postgres:
create table fubar (
name1 text,
name2 text, ...,
key integer);
I want to write a function which returns field values from fubar given the column names:
function getFubarValues(col_name text, key integer) returns text ...
where getFubarValues returns the value of the specified column in the row identified by key. Seems like this should be easy.
I'm at a loss. Can someone help? Thanks.
Klin's answer is a good (i.e. safe) approach to the question as posed, but it can be simplified:
PostgreSQL's -> operator allows expressions. For example:
CREATE TABLE test (
id SERIAL,
js JSON NOT NULL,
k TEXT NOT NULL
);
INSERT INTO test (js,k) VALUES ('{"abc":"def","ghi":"jkl"}','abc');
SELECT js->k AS value FROM test;
Produces
value
-------
"def"
So we can combine that with row_to_json:
CREATE TABLE test (
id SERIAL,
a TEXT,
b TEXT,
k TEXT NOT NULL
);
INSERT INTO test (a,b,k) VALUES
('foo','bar','a'),
('zip','zag','b');
SELECT row_to_json(test)->k AS value FROM test;
Produces:
value
-------
"foo"
"zag"
Here I'm getting the key from the table itself but of course you could get it from any source / expression. It's just a value. Also note that the result returned is a JSON value type (it doesn't know if it's text, numeric, or boolean). If you want it to be text, just cast it: (row_to_json(test)->k)::TEXT
Now that the question itself is answered, here's why you shouldn't do this, and what you should do instead!
Never trust any data. Even if it already lives inside your database, you shouldn't trust it. The method I've posted here is safe against SQL injection attacks, but an attacker could still set k to 'id' and see a column which was not intended to be visible to them.
A much better approach is to structure your data with this type of query in mind. Postgres has some excellent datatypes for this; HSTORE and JSON/JSONB. Merge your dynamic columns into a single column with one of those types (I'd suggest HSTORE for its simplicity and generally being more complete).
This has several advantages: your schema is well-defined and does not need to change if you add more dynamic columns, you do not need to perform expensive re-casting (i.e. row_to_json), and you are able to take advantage of indexes on your columns (thanks to PostgreSQL's functional indexes).
The equivalent to the code I wrote above would be:
CREATE EXTENSION HSTORE; -- necessary if you're not already using HSTORE
CREATE TABLE test (
id SERIAL,
cols HSTORE NOT NULL,
k TEXT NOT NULL
);
INSERT INTO test (cols,k) VALUES
('a=>"foo",b=>"bar"','a'),
('a=>"zip",b=>"zag"','b');
SELECT cols->k AS value FROM test;
Or, for automatic escaping of your values when inserting, you can use one of:
INSERT INTO test (cols,k) VALUES
(hstore( 'a', 'foo' ) || hstore( 'b', 'bar' ), 'a'),
(hstore( ARRAY['a','b'], ARRAY['zip','zag'] ), 'b');
See http://www.postgresql.org/docs/9.1/static/hstore.html for more details.
You can use dynamic SQL to select a column by name:
create or replace function get_fubar_values (col_name text, row_key integer)
returns setof text language plpgsql as $$begin
return query execute 'select ' || quote_ident(col_name) ||
' from fubar where key = $1' using row_key;
end$$;

insert string into text [] column

I have the following issue.
I will receive input as a text from a webservice to insert into a certain psql table. assume
create table test ( id serial, myvalues text[])
the recieved input will be:
insert into test(myvalues) values ('this,is,an,array');
I want to create a trigger before insert that will be able to convert this string to a text [] and insert it
first Idea that came in my mind was to create a trigger before insert
create function test_convert() returns trigger as $BODY%
BEGIN
new.myvalues = string_to_array(new.myvalues,',')
RETURNS NEW
END; $BODY$ language plpgsql
but this did not work
You can use the string_to_array function to convert your string into an string array within your insert query:
INSERT INTO test ( myvalues )
VALUES ( string_to_array( 'this,is,an,array', ',' ) );
Suppose you receive text in the following format this is an array and you want to convert it to this,is,an,array then you can use string_to_array('this is an array', ' ') and it will be converted. However if you are receiving comma separated then you can just used it.
Creating the Table Schema Like this,
CREATE TABLE expert (
id VARCHAR(32) NOT NULL,
name VARCHAR(36),
twitter_id VARCHAR(40),
coin_supported text[],
start_date TIMESTAMP,
followers BIGINT,
PRIMARY KEY (id)
);
Inserting values like this will help you to insert array,
insert into expert(id, name, twitter_id, coin_supported, start_date, followers) values('9ed1cdf2-564c-423e-b8e2-137eg', 'dev1', 'dev1#twitter', '{"btc","eth"}', current_timestamp, 12);

Cassandra CQL ALTER Table with timeuuid column

I tried ALTER TABLE with a valid timeuuid column name -
cqlsh:dbase> ALTER TABLE jdata ADD 4f8eca60-1498-11e4-b6e6-ed7706c00c12 timeuuid;
Bad Request: line 1:24 no viable alternative at input '4f8eca60-1498-11e4-b6e6-ed7706c00c12'
So, I next tried with quotes and it worked -
cqlsh:dbase> ALTER TABLE jdata ADD "4f8eca60-1498-11e4-b6e6-ed7706c00c12" timeuuid;
cqlsh:dbase>
But the table description now looks ugly with column name in quotes -
cqlsh:dbase> describe columnfamily jdata;
CREATE TABLE jdata (
abc text,
"4f8eca60-1498-11e4-b6e6-ed7706c00c12" timeuuid,
xyz text,
PRIMARY KEY ((abc), xyz)
) WITH
bloom_filter_fp_chance=0.010000 AND
blah blah;
So I need help with a ALTER command to create timeuuid column using CQL without quotes.
The NAME of the column is a String by definition.
So you can't put anything different from a String as column name.
create table invalidnames (2 text primary key, 5 int);
**Bad Request**: line 1:47 mismatched input '5' expecting ')'
while with strings works
create table validnames (two text primary key, five int);
The name of the column and the type of the column are not related in any way
HTH,
Carlo