I have a column name demo.
create table demo (
id int,
name varchar,
address varchar,
designation varchar
);
I want to achieve the below scenario in one query
If I pass an empty string like "" then query will return all values in table
If I pass 'av' then query should match 'av' contins string in whole table column(name, address, designation);
You need a WHERE clause like this:
WHERE name LIKE '%av%'
OR address LIKE '%av%'
OR designation LIKE '%av%'
Beware of SQL injection when you construct the search pattern.
Related
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.
I have list of value like 2,3,4(comma separated) and a table which has ids like 1,2,3,4,5,6 call it as table1. From table1 table i have emp_name.
Here what i want is to get list of employees in comma separated values based on list give in the condition.
To achieve this i tried group concate, and find_in set but unable to get desired out put.
eg. select emp_name from emp_table where emp_id in('2,3,4', '1,2,3,4,5,6');
desired output. mr2,mr3,mr4
I know i can achieve it by looping through it, but i want mysql way.
Any help would be appreciable.
Thanyou
Having a table like
CREATE TABLE employees (
id INTEGER NOT NULL AUTOINCREMENT,
name VARCHAR(100),
PRIMARY KEY (id)
);
you may query it like this
SELECT GROUP_CONCAT(name) AS employee FROM employees WHERE id IN (1,2,3,4,5,6);
and the result would be
Sandeep,Mohammed,Sabri,Ashtam,Tamal
I'm currently developing an app and encountered a problem when trying to create a query on a table that uses a custom type.
Here is an example table and type,
CREATE TYPE address AS (
street varchar(40),
city varchar(25),
zip varchar(5)
);
CREATE TABLE houses (
id SERIAL PRIMARY KEY,
address address
);
I need to retrieve a list with all the cities stored in the table houses.
Here's what I tried to do:
SELECT address.city
FROM houses
GROUP BY address.city
It detects address.city as a table. Is there any way to do what I want to do in PostgreSQL?
I would not use a compound type like that in a table. But you can still do this, use parenthesis.
SELECT (address).city
FROM houses
GROUP BY (address).city
From the docs
To access a field of a composite column, one writes a dot and the field name, much like selecting a field from a table name. In fact, it's so much like selecting from a table name that you often have to use parentheses to keep from confusing the parser.
Instead, I would use a jsonb. Or, if you're going to use a compound type you should use stdaddr from PostGIS.
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 want to create an enum from distinct values of a column in PostgreSQL. Instead of creating an enum from all labels, I want to create it using a query to get all possible values of the type. I am expecting something like:
CREATE TYPE genre_type AS ENUM
(select distinct genre from movies);
But I am not allowed to do this. Is there any way to achieve this?
If genre types are in any way dynamic, i.e. you create new ones and rename old ones from time to time, or if you want to save additional information with every genre type, #mu's advice and #Marcello's implementation would be worth considering - except you should just use type text instead of varchar(20) and consider ON UPDATE CASCADE for the fk constraint.
Other than that, here is the recipe you asked for:
DO
$$
BEGIN
EXECUTE (
SELECT format('CREATE TYPE genre_type AS ENUM (%s)'
,string_agg(DISTINCT quote_literal(genre), ', '))
FROM movies);
END
$$
You need dynamic SQL for that. The simple way is a DO command (PostgreSQL 9.0+).
Make sure your strings are properly escaped with quote_literal().
I aggregate the string with string_agg() (PostgreSQL 9.0+).
I think you can't do that by design.
http://www.postgresql.org/docs/9.1/static/datatype-enum.html
Enumerated (enum) types are data types that comprise a static, ordered
set of values.
The "DISTINCT" keyword in your SELECT clause makes me think your schema is not fully normalized.
For example:
CREATE TABLE movies(
...
genre VARCHAR(20)
...
);
SELECT DISTINCT genre FROM movies;
Should become:
CREATE TABLE genres(
id SERIAL PRIMARY KEY,
name VARCHAR(20)
);
CREATE TABLE movies (
id SERIAL PRIMARY KEY,
title VARCHAR(200),
genre INTEGER REFERENCES genres(id)
);
SELECT name FROM genres;
A trivial approach would be to execute the SELECT in a client and then copy the names from it.
I think that is about everything you can do. If you look at the documentation http://www.postgresql.org/docs/9.3/static/sql-createtype.html you will notice that there is written CREATE TYPE name AS ENUM ( [ 'label' [, ... ] ] ) so what is not there is the keyword expression. That means that after ENUM there may not be an expression but only a list of labels.
You may want to follow #muistooshort's advice and create a genres table (that you can fill with an INSERT ... SELECT ...) and then create a foreign key to that table.
It can be done in pgsql. Here's inline code to do it:
DO $$
DECLARE temp text;
BEGIN
SELECT INTO temp string_agg(DISTINCT quote_literal(genre),',') FROM movies;
EXECUTE 'CREATE TYPE foo AS ENUM ('||temp||')';
END$$;
fiddle