How to escape underscores in Postgresql - postgresql

When searching for underscores in Postgresql, literal use of the character _ doesn't work. For example, if you wanted to search all your tables for any columns that ended in _by, for something like change log or activity information, e.g. updated_by, reviewed_by, etc., the following query almost works:
SELECT table_name, column_name FROM information_schema.columns
WHERE column_name LIKE '%_by'
It basically ignores the underscore completely and returns as if you'd searched for LIKE '%by'. This may not be a problem in all cases, but it has the potential to be one. How to search for underscores?

You need to use a backslash to escape the underscore. Change the example query to the following:
SELECT table_name, column_name FROM information_schema.columns
WHERE column_name LIKE '%\_by'

Just ran into the same issue and the single backslash wasn't working as well. I found this documentation on the PostgreSQL community and it worked:
The correct way is to escape the underscore with a backslash. You
actually have to write two backslashes in your query:
select * from
foo where bar like '%\\_baz'
The first backslash quotes the second one for the query parser, so
that what ends up inside the system is %\_baz, and then the LIKE
function knows what to do with that.
Therefore use something like this:
SELECT table_name, column_name FROM information_schema.columns
WHERE column_name LIKE '%\\_by'
Source Documentation: https://www.postgresql.org/message-id/10965.962991238%40sss.pgh.pa.us

Related

Need replace text with single quotes in SQL

I need to make a script that make a replacement of all the registers of a column that contains: '#xxxx', removing the single quotes. (xxxx could be empty or any string. The #, is neccesary, the simple quotes too).
I'm implementing something like this, but it doesn't work for me, because the 'REPLACE' function accepts Strings as parameters, instead of accepting other functions.
Thanks
I tried
UPDATE MY_TABLE SET MY_COLUMN = REPLACE('MY_COLUMN',
SELECT "MY_COLUMN" FROM MY_TABLE WHERE "MY_COLUMN" like '%''#%',
SELECT TRIM( '%''%' FROM MY_TABLE WHERE "MY_COLUMN" like '%''#%'))
Its unclear what dbms you are using, but here is what I would so in SQLServer, you can modify for you dbms if not this.
They key point here is you are doing this the wrong way round, you use the Replace function on each row, not pass the record set into the replace.
UPDATE mt
SET myColumn = REPLACE(myColumn, '''','')
FROM myTable mt
WHERE myColumn LIKE '%''#%'

Postgresql: literal table names

I am making an application that needs to construct Postgresql queries that will execute successfully in scenarios when table names are reserved keywords etc.
In Sql Server syntax this is achieved by wrapping everything in square brackets [] i.e. SELECT * FROM [database].[schema].[table_name].
I thought the equivalent in Postgresql was the use of double quotes "" i.e. SELECT * FROM "database"."schema"."table_name".
However, when I try this in Postgresql I get the error
Relation X doesn't exist
This works:
SELECT * FROM "postgres"."schema_a".Academic_Attainment
But this doesn't:
SELECT * FROM "postgres"."schema_a"."Academic_Attainment"
Related to: Escaping keyword-like column names in Postgres
Any suggestions?
As documented in the manual unquoted identifiers are folded to lowercase.
A quoted identifier is also case sensitive, so "Foo" is a different name than "foo".
So the name Academic_Attainment is the same as academic_attainment. If you really insist on using those dreaded double quotes, then you need to use a lower case identifier:
SELECT *
FROM "schema_a"."academic_attainment"
In general it's strongly recommended to not use quoted identifiers at all. As a rule of thumb: never use double quotes and you are fine.
If you are constructing dynamic SQL, use the format() function to do that together with the %I placeholder. It will take care of quoting if necessary (and only then), e.g.
format('select * from %I.%I', 'public', 'some_table') yields select * from public.some_table but format('select * from %I.%I', 'public', 'group') yields select * from public."group"
Unrelated to your question: Postgres doesn't support cross-database queries, so you should not get into the habit including the database name into your fully qualified names. The syntax you are using only works because you are connected to the database postgres. So I would recommend to stop using the database name in any table reference.

Is there a way to use ::regclass in a case sensitive way?

I'm wondering if there is a way to use ::regclass to convert a string to a pg_class.oid in a way that respects case sensitivity. Let me give an example. It's often handy to use ::regclass to get the oid of a table, e.g. to list all columns of a table
SELECT * FROM pg_attribute WHERE attrelid = 'public.my_table'::regclass
However, ::regclass implicitly converts the input to all lowercase before doing the search. (This is similar to how PGSQL will interpret table names in SQL commands, if you don't surround them with double quotes.) This means if your table is called MY_table, then you cannot use casting to ::regclass to get its oid.
I know you can use other means, e.g. use pg_class.relname and pg_class.relnamespace. This question is specifically about using ::regclass, because ::regclass is more convenient (if I can find a way to make it work in a case sensitive way).
I've tried
SELECT * FROM pg_attribute WHERE attreloid = '"public.my_table"'::regclass
but that includes the double-quotes in the name it searches.
The reason my second query didn't work is because the double quotes were around the . character. So here's how to do it.
SELECT * FROM pg_attribute WHERE attreloid = '"public"."my_table"'::regclass

Which query injection breaks this SQL if input is validated again regex?

SELECT COLUMN_NAME FROM TABLE_NAME WHERE COLUMN_NAME = {INPUT};
I don't have a connection directly to a database, so I have to send the query as string. I will validate the input value against this pattern "[a-zA-Z]\s[a-zA-Z]", so I haven't found a way to break this query.
I think you meant [a-zA-Z]\s[a-zA-Z].
Seems to works on all examples of this page:
http://www.unixwiz.net/techtips/sql-injection.html

select data with single quote only- Postgres

im using Like to select all data which has single quote in name like Jon's.
select * from users where file_name like '%'%';
I then want to remove the ' from all results.
Ideas?
Double quotes in SQL to escape them:
select * from users where file_name like '%''%';
(For any vaguely recent PostgreSQL version; the non-standard escape-string phrasing E'%\'%' will work with even very old PostgreSQL versions, but not other databases.)
It sounds like you want to remove those characters from the file names. If so, something like the untested:
update users
set file_name = replace(file_name, '''', '')
should do the trick.