Right now I'm trying to create a filter that would give me every result from start of the month. The query looks like this:
cur.execute('SELECT SUM(money_amount) '
f'FROM expense WHERE created >= "{first_day_of_month}"'
But I'm getting such error: psycopg2.errors.UndefinedColumn: column "2022-08-01" does not exist
my createtable.sql:
CREATE TABLE budget(
codename varchar(255) PRIMARY KEY,
daily_expense INTEGER );
CREATE TABLE category(
codename VARCHAR(255) PRIMARY KEY,
name VARCHAR(255),
is_basic_expense BOOLEAN,
aliases TEXT );
CREATE TABLE expense(
id SERIAL PRIMARY KEY,
money_amount INTEGER,
created DATE,
category_codename VARCHAR(255),
raw_text TEXT,
FOREIGN KEY(category_codename) REFERENCES category(codename) );
What is wrong and why the column does not exist, when it is?
This is probably the most common reason to get a "column does not exist" error: using double quotes. In PostgreSQL, double quotes aren't used for strings, but rather for identifiers. For example, if your column name had a space in it, you wouldn't be able to write WHERE the date > '2022-08-01', but you would be able to write WHERE "the date" > '2022-08-01'. Using double quotes around a string or stringy thing like a date gets interpreted as an attempt to use an identifier, and since you're using it where a value should be it will usually be interpreted as trying to identify a column in particular. I make this mistake at least once a week. Instead, use single quotes or placeholders.
Related
I have the below table
BEGIN;
CREATE TABLE IF NOT EXISTS "public".appevents (
id uuid DEFAULT uuid_generate_v4() NOT NULL,
"eventId" uuid NOT NULL,
name text NOT NULL,
"creationTime" timestamp without time zone NOT NULL,
"creationTimeInMilliseconds" bigint NOT NULL,
metadata jsonb NOT NULL,
PRIMARY KEY(id)
);
COMMIT;
I would like to extract with a query the metadata jsonb column as a row and tried with the below query.
SELECT
userId
FROM
appevents, jsonb_to_record(appevents.metadata) as x(userId text)
Unfortunately, all the rows returned for userid have the value NULL which is not true. The only weird thing noticed is that it is converting camelcase to lowercase but doesn't seem like the issue.
Here are the 2 records I currently have in the database where userId exists.
The only weird thing noticed is that it is converting camelcase to lowercase but doesn't seem like the issue.
Actually that is the culprit - column names are case-insensitive by default, and userId is normalised to userid, for which the JSON doesn't contain a property. Quoting the identifier (… as x("userId" text)) should work.
However, there's a much simpler solution for accessing json object properties as text: the ->> operator. You can use
SELECT metadata->>'userId' AS userid FROM appevents
I tried to create a table with postgresql query:
CREATE TABLE customer_account(ID_account integer primary key, customer_name (lastname) text);
but it gives an error message:
ERROR: syntax error at or near "("
LINE 5: customer_name (lastname) text,
Probably the problem comes from the bracket, and I already tried like
CREATE TABLE customer_account("ID_account" primary key, "customer_name (lastname)" text);
But it also gave me a similar error message.
How to correct the query? I really need to use bracket.
Using " will work, but you are missing the data type for your primary key:
CREATE TABLE customer_account
(
"ID_account" integer primary key,
--^ here
"customer_name (lastname)" text
);
Online example
But I strongly suggest you do not use quoted identifiers.
They will give you much more trouble in the long run then they are worth it.
I would recommend to use something like this:
CREATE TABLE customer_account
(
account_id integer primary key,
customer_lastname text
);
("ID" as a prefix sounds quite strange in English)
I have placed a file in my docker-entrypoint-initdb.d/ directory. Here is what is in the file:
CREATE TABLE user_test (
user_id INTEGER,
name VARCHAR(100),
email VARCHAR(128),
active_flg BOOLEAN,
type VARCHAR(20),
CONSTRAINT pk_user PRIMARY KEY (user_id)
);
The error I am getting is psql:/docker-entrypoint-initdb.d/0001-initial-database-design.sql:8: ERROR: syntax error at or near "CREATE".
What am I missing in being able to run a file? How do I change this file to work?
USER is a reserved keyword in Postgres, see the documentation. In general, you should avoid naming your tables and columns using reserved SQL keywords. If you really wanted to proceed as is, then place user into double quotes:
CREATE TABLE "user" (
user_id INTEGER,
name VARCHAR(100),
email VARCHAR(128),
active_flg BOOLEAN,
type VARCHAR(20),
CONSTRAINT pk_user PRIMARY KEY (user_id)
);
But, keep in mind that if you choose to name your table user, then you will forever have to escape it with double quotes.
We're in process of converting over from SQL Server to Postgres. I have a scenario that I am trying to accommodate. It involves inserting records from one table into another, WITHOUT listing out all of the columns. I realize this is not recommended practice, but let's set that aside for now.
drop table if exists pk_test_table;
create table public.pk_test_table
(
recordid SERIAL PRIMARY KEY NOT NULL,
name text
);
--example 1: works and will insert a record with an id of 1
insert into pk_test_table values(default,'puppies');
--example 2: fails
insert into pk_test_table
select first_name from person_test;
Error I receive in the second example:
column "recordid" is of type integer but expression is of type
character varying Hint: You will need to rewrite or cast the
expression.
The default keyword will tell the database to grab the next value.
Is there any way to utilize this keyword in the second example? Or some way to tell the database to ignore auto-incremented columns and just them be populated like normal?
I would prefer to not use a subquery to grab the next "id".
This functionality works in SQL Server and hence the question.
Thanks in advance for your help!
If you can't list column names, you should instead use the DEFAULT keyword, as you've done in the simple insert example. This won't work with a in insert into ... select ....
For that, you need to invoke nextval. A subquery is not required, just:
insert into pk_test_table
select nextval('pk_test_table_id_seq'), first_name from person_test;
You do need to know the sequence name. You could get that from information_schema based on the table name and inferring its primary key, using a function that takes just the table name as an argument. It'd be ugly, but it'd work. I don't think there's any way around needing to know the table name.
You're inserting value into the first column, but you need to add a value in the second position.
Therefore you can use INSERT INTO table(field) VALUES(value) syntax.
Since you need to fetch values from another table, you have to remove VALUES and put the subquery there.
insert into pk_test_table(name)
select first_name from person_test;
I hope it helps
I do it this way via a separate function- though I think I'm getting around the issue via the table level having the DEFAULT settings on a per field basis.
create table public.pk_test_table
(
recordid integer NOT NULL DEFAULT nextval('pk_test_table_id_seq'),
name text,
field3 integer NOT NULL DEFAULT 64,
null_field_if_not_set integer,
CONSTRAINT pk_test_table_pkey PRIMARY KEY ("recordid")
);
With function:
CREATE OR REPLACE FUNCTION func_pk_test_table() RETURNS void AS
$BODY$
INSERT INTO pk_test_table (name)
SELECT first_name FROM person_test;
$BODY$
LANGUAGE sql VOLATILE;
Then just execute the function via a SELECT FROM func_pk_test_table();
Notice it hasn't had to specify all the fields- as long as constraints allow it.
I have a set of files on S3 that I am trying to load into redshift.
I am using the amazon data pipeline to do it. the wizard took the cluster, db and file format info but I get errors that a primary key is needed to keep existing fields in th table (KEEP_EXISTING) on the table
My table schema is:
create table public.Bens_Analytics_IP_To_FileName(
Day date not null encode delta32k,
IP varchar(30) not null encode text255,
FileName varchar(300) not null encode text32k,
Count integer not null)
distkey(Day)
sortkey(Day,IP);
so then I added a composite primary key on the table to see if it will work, but I get the same error.
create table public.Bens_Analytics_IP_To_FileName(
Day date not null encode delta32k,
IP varchar(30) not null encode text255,
FileName varchar(300) not null encode text32k,
Count integer not null,
primary key(Day,IP,FileName))
distkey(Day)
sortkey(Day,IP);
So I decided to add an identity column as the last column and made it the primary key but then the COPY operation wants a value in the input files for that identity column which did not make much sense
ideally I want it to work without a primary key or a composite primary key
any ideas?
Thanks
Documentation is not in a great condition. They have added a 'mergeKey' concept that can be any arbitrary key (announcement, docs). You should not have to define a primary key on table with this.
But you would still need to supply a key to perform join between your new data coming in and the existing data in redshift table.
In Edit Pipeline, under Parameters, there is a field named: myPrimaryKeys (optional). Enter you Pk there, instead of adding it to your table definition.