How can I insert into PostgreSQL using Perl, DBI and placeholders? - perl

I am trying to insert a row into a pSQL table, specifying both keys and values as placeholders:
my #keys = keys %db_entr;
my #vals = values %db_entr;
my #items = (#keys, #values);
my $dbh = DBI->connect("DBI:Pg:dbname=testdb;host=localhost", "username", 'password', {'RaiseError' => 1});
my $sth = $dbh->prepare("INSERT INTO grid ( ?, ?, ? ) values ( ?, ?, ? )");
my $rows = $sth->execute(#items);
print "$rows effected\n";
However, whatever I do, this gives me an error:
DBD::Pg::st execute failed: ERROR: syntax error at or near "$1"
LINE 1: INSERT INTO grid ( $1, $2, ...
^ at ./file.pl line 262, <STDIN> line 11.
Does anyone have an idea of what I might be doing wrong?

You cannot use placeholders for column names like this:
INSERT INTO grid (?, ?, ?) VALUES (?, ?, ?)
You must specify column names explicitly and can use placeholders for values only:
INSERT INTO grid (x, y, z) VALUES (?, ?, ?)

You can't use placeholders for column names in the prepare call. The best you can do is to either interpolate the variable names into the SQL string or use sprintf to do the equivalent.
This is an example, but you may need to do something different. Note that it modifies the #items array, and you need to call prepare again each time the contents of #items may have changed.
my $sth = $dbh->prepare(
sprintf "INSERT INTO grid ( %s, %s, %s ) values ( ?, ?, ? )",
splice #items, 0, 3
);
my $rows = $sth->execute(#items);
print "$rows affected\n";

Related

DB2 XML Select multiple rows in Single statements

In My code,
SELECT X.DEP_ID
FROM (SELECT XMLPARSE (DOCUMENT '<root><DEP_ID>1000000004</DEP_ID><DEP_ID>1000000005</DEP_ID></root>') AS ELEMENT_VALUE
FROM SYSIBM.SYSDUMMY1) AS A,
XMLTABLE (
'$d/root'
PASSING Element_value AS "d"
COLUMNS
DEP_ID VARCHAR (10) PATH 'DEP_ID'
) AS X;
Need as result of:
DEP_ID
1000000004
1000000005
If its single values means it working that means only one DEP_ID in xml.
But Multiple return means it will show error.
How to get the output as like above in db2.
Wrong row-xquery-expression-constant.
Try this:
SELECT X.DEP_ID
FROM
(
SELECT XMLPARSE (DOCUMENT '<root><DEP_ID>1000000004</DEP_ID><DEP_ID>1000000005</DEP_ID></root>') AS ELEMENT_VALUE
FROM SYSIBM.SYSDUMMY1
) AS A
, XMLTABLE
(
'$d/root/DEP_ID' PASSING Element_value AS "d"
COLUMNS
DEP_ID VARCHAR (10) PATH '.'
) AS X;

Storing timestamp in PostgreSQL gives an error: "cannot cast type bigint to timestamp without time zone"

I've created my table with the following code:
CREATE TABLE "STORES" (
"STOREGLOBALID" SERIAL NOT NULL ,
"STOREUPDATEDATETIME" TIMESTAMP NOT NULL,
"CHAINID" BIGINT ,
"CHAINNAME" VARCHAR(50) ,
"SUBCHAINID" SMALLINT ,
"SUBCHAINNAME" VARCHAR(50) ,
"STOREID" SMALLINT ,
"STORENAME" VARCHAR(50) ,
"STORETYPE" SMALLINT ,
"ADDRESS" VARCHAR(50) ,
"CITY" VARCHAR(50) ,
PRIMARY KEY ("STOREGLOBALID")
);
When I try to insert timestamp by using the following SQL for preparing statement:
INSERT INTO "STORES"
("STOREGLOBALID",
"STOREUPDATEDATETIME",
"CHAINID",
"CHAINNAME",
"SUBCHAINID",
"SUBCHAINNAME",
"STOREID",
"STORENAME",
"STORETYPE",
"ADDRESS",
"CITY")
VALUES (DEFAULT, cast(? as timestamp), ?, ?, ?, ?, ?, ?, ?, ?, ?)
And the following Java code:
ps = con.prepareStatement(sql);
ps.setLong(1, store.getChainId());
ps.setTimestamp(2, new Timestamp(1000000000)); //this value is only for test purposes, actual value gives the same error
I get the following error:
cannot cast type bigint to timestamp without time zone Position: 235
I understand that I need to provide a timestamp, but when I do it as following:
ps.setTimestamp(2, new Timestamp(1000000000), Calendar.getInstance(TimeZone.getTimeZone("UTC")));
I get the same error. What am I doing wrong? Thank you.
The first argument of your prepared statement is used in
cast(? as timestamp)
and the result is stored in STOREUPDATEDATETIME, of type TIMESTAMP. And you're passing a long (store.getChainId()) as argument. So you're trying to cast a long to a timestamp.
The second argument of your prepared statement is stored in CHAINID, of type BIGINT. And you're passing a Timestamp as argument (new Timestamp(1000000000)). So PostgreSQL tries to transform this timestamp into a bigint.
The SQL should be
INSERT INTO "STORES"
("STOREGLOBALID",
"STOREUPDATEDATETIME",
"CHAINID",
"CHAINNAME",
"SUBCHAINID",
"SUBCHAINNAME",
"STOREID",
"STORENAME",
"STORETYPE",
"ADDRESS",
"CITY")
VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
And the Java should be
ps.setTimestamp(1, new Timestamp(1000000000));
ps.setLong(2, store.getChainId());

Postgres 9.3 gives ERROR: Array values must start with ... for hex bytea value

Given a simple table:
PGresult *res = PQexec(usersconn, "CREATE TABLE userfiles (username
varchar[100] PRIMARY KEY, mydata bytea);");
I try to add a data with this:
PGresult *res = PQexec(usersconn, "INSERT into userfiles VALUES (
'peter' , '\\\\x1A' );" );
or this:
PGresult *res = PQexec(usersconn, "INSERT into userfiles VALUES ( 'peter' , '\x1A' );" );
and I get an error message about array values must start with ...
What am I doing wrong in trying to insert a simple hex constant into this record?
Hex values have to use escape syntax:
INSERT into userfiles VALUES ( 'peter' , e'\\x1A' );
See http://www.postgresql.org/docs/9.3/static/datatype-binary.html
Your problem isn't the bytea field, it's the username field.
varchar[100] is an array of 100 varchar elements, each of which is of unbounded length.
I think you probably meant varchar(100), a single varchar scalar of length 0-100.

How to use limit in sqlite

get '/' => sub {
my $db = connect_db();
my $sql = 'select id, title, text from entries order by id desc limit 3 offset 4';
my $sth = $db->prepare($sql) or die $db->errstr;
$sth->execute or die $sth->errstr;
template 'show_entries.tt', {
'msg' => get_flash(),
'add_entry_url' => uri_for('/add'),
'entries' => $sth->fetchall_hashref('id'),
};
};
I want to show on the main page the 3 themes , but for some reason Shows all. What i'm doing wrong?
Works for me
$ perl -E'
use DBI;
my $dbh = DBI->connect("dbi:SQLite:", undef, undef,
{ PrintError => 0, RaiseError => 1, AutoCommit => 1 });
$dbh->do("CREATE TEMP TABLE MyTable ( id INT )");
$dbh->do("INSERT INTO MyTable VALUES (?)", undef, $_) for 1..9;
my $sql = "SELECT * FROM MyTable LIMIT 3 OFFSET 4";
my $sth = $dbh->prepare($sql);
$sth->execute();
say for keys %{ $sth->fetchall_hashref("id") };
'
5
6
7
Or from the command line client
$ sqlite3
SQLite version 3.3.6
Enter ".help" for instructions
sqlite> CREATE TEMP TABLE MyTable ( id INT );
sqlite> INSERT INTO MyTable VALUES (1);
sqlite> INSERT INTO MyTable VALUES (2);
sqlite> INSERT INTO MyTable VALUES (3);
sqlite> INSERT INTO MyTable VALUES (4);
sqlite> INSERT INTO MyTable VALUES (5);
sqlite> INSERT INTO MyTable VALUES (6);
sqlite> INSERT INTO MyTable VALUES (7);
sqlite> INSERT INTO MyTable VALUES (8);
sqlite> INSERT INTO MyTable VALUES (9);
sqlite> SELECT * FROM MyTable LIMIT 3 OFFSET 4;
5
6
7
sqlite> .q
Versions:
$ perl -MDBI -E'
my $dbh = DBI->connect("dbi:SQLite:", undef, undef);
say for
$DBD::SQLite::VERSION,
$dbh->{sqlite_version}
'
1.40
3.7.17

Postgresql Oledb column name quoting

I have:
INSERT INTO XYZ (c1, c2, range) VALUES (?, ?, ?)
OleDb call fails here because of range is a reserved keyword - how to quote it through the OleDB?
Use double quotes ":
INSERT INTO XYZ (c1, c2, "range") VALUES (?, ?, ?)