postgresql replace function using pattern matching characters - sql

I am having a table named "OptionsDetail" with column named "URL" in postgresql database. The "URL" column contain the following data
URL
http://www.site1.com/ebw/file1/detail.action?cid=1
http://www.another2.com/ebw/file1/detail.action?cid=11&code=MYCODE
http://www.anothersite3.com/ebw/file1/detail.action?cid=12&code=ANOTHERCODE&option=ROOM
Now I want to replace the data in URL to
URL
/file1/detail.action?cid=1
/file1/detail.action?cid=11&code=MYCODE
/file1/detail.action?cid=12&code=ANOTHERCODE&menu=ROOM
I wrote the following query to perform the above functionality
UPDATE "OptionsDetail" SET "URL" = replace("URL",'http://%/ebw/file1','/file1') WHERE "URL" LIKE '%/ebw/file1%';
And also another way I wrote like this
UPDATE "OptionsDetail" SET "URL" = replace("URL",'%/ebw/file1','/file1') WHERE "URL" LIKE '%/ebw/file1%';
Query is executing successfully saying like for ex: 200 rows affected but "URL" column data is not changing the way I need, the data is remaining as it is.
Please help me to resolve this issue

The problem is that replace doesn't support wildcards like %:
replace("URL",'http://%/ebw/file1','/file1')
^^^
You can use regexp_replace instead:
UPDATE YourTable
SET URL = regexp_replace(URL, 'http://.*/ebw/file1', '/file1')
WHERE URL LIKE '%/ebw/file1%'
Note that regexp_replace uses different wildcards than like. In regular expressions, "Any number of any character" is .* instead of %.
See it working at SQL Fiddle.

Related

Bigquery named parameters regex in Java

I am looking for a way to use a regex as value in a named parameter in the Java SDK. According to the documentation, there is no datatype for that, and using a String parameter does not work.
Is there any way to use a regex as value in a named parameter?
QueryParameterValue Class has no datatype for that:
https://googleapis.dev/java/google-cloud-clients/0.91.0-alpha/com/google/cloud/bigquery/QueryParameterValue.html#of-T-com.google.cloud.bigquery.StandardSQLTypeName-
A regex in the query would e.g. look like this:
REGEXP_CONTAINS(some_attribute, r"^any\sregex\ssearchstring$")
and should be replaced by a named parameter like:
REGEXP_CONTAINS(some_attribute, #named_regex_parameter)
I tried different syntax in the query like
REGEXP_CONTAINS(some_attribute, r#named_regex_parameter)
etc. but none of them worked. The #named_regex_parameter is of type String. I tried to use values in the form of r"regex_expression" and just the regex_expression in the parameter value.
Seems like I need to build the query String without a named parameter for the regex part. Any hints to solve this with parameters would be really appreciated!
//Edit: added code example how the named parameters are used in the query config
QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(query)
.setDestinationTable(TableId.of(destinationDataset, destinationTable))
.setAllowLargeResults(true)
.setCreateDisposition(CreateDisposition.CREATE_IF_NEEDED)
.setTimePartitioning(partitioning)
.setWriteDisposition(WriteDisposition.WRITE_APPEND)
.setParameterMode("NAMED")
.addNamedParameter("regexExpressionParam", QueryParameterValue.string(someRegexExpressionStringVariable)) //this does not work
.addNamedParameter("someStringParam", QueryParameterValue.string(stringVariable))
.setPriority(Priority.BATCH)
.build();
The query should use the parameter #regexExpressionParam like so:
REGEXP_CONTAINS(theAttributeToQuery, #regexExpressionParam))
You need to pass the regular expression string without r'...'
I had a very similar problem with running parameterized queries on Python: it was something like this.
from google.cloud import bigquery
regex_input = "^begin_word.*end_here$"
# Construct a BigQuery client object.
client = bigquery.Client()
query = """
SELECT word, word_count
FROM `bigquery-public-data.samples.shakespeare`
WHERE REGEXP_CONTAINS(word, #regex)
ORDER BY word_count DESC;
"""
job_config = bigquery.QueryJobConfig(
query_parameters=[
bigquery.ScalarQueryParameter("regex", "STRING", f"r'{regex_input}'"),
]
)
query_job = client.query(query, job_config=job_config)
At first, I thought the input had to be wrapped by r'...'; just like how I normally write a regex on BQ explorer.
I tried to modify the string input to make it like a regular expression, which was this pard f"r'{regex_input}'" of the code.
but apparently BQ correctly escapes string without our help and I can just pass down the regex string like bigquery.ScalarQueryParameter("regex", "STRING", regex_input)

Querying full and sub-strings via multi-valued parameter using SQL

I am building a report with Microsoft SSRS (2012) having a multi-value parameter #parCode for the user to filter for certain codes. This works perfectly fine. Generally, my query looks like this:
SELECT ...
FROM ...
WHERE
TblCode.Code IN (#Code)
ORDER BY...
The codes are of following type (just an excerpt):
C73.0
C73.1
...
C79.0
C79.1
C79.2
Now, in additon to filtering for multiple of these codes I would like to als be able to filter for sub-strings of the codes. Meaning, when the user enters (Example 1)
C79
for #parCodes The output should be
C79.0
C79.1
C79.2
So eventually the user should be able to enter (Example 2)
C73.0
C79
for #parCodes and the output would be
C73.0
C79.0
C79.1
C79.2
I managed to implement both functionalities seperately, so either filtering for multiple "complete" codes or filterting for sub-string of code, but not both simultaneously.
I tried to do something like
...
WHERE
TblCode.Code IN (#parCode +'%')
ORDER BY...
but this screws up the Example 2. On the other hand, if I try to work with LIKE or = instead of IN statement, then I won't be able to make the parameter multi-valued.
Does anyone have an idea how to realize such functionality or whether IN statement pared with multi-valued parameters simply doesn't allow for it?
Thank you very much!
Assuming you are using SQL server
WHERE (
TblCode.Code IN (#parCode)
OR
CASE
WHEN CHARINDEX('.', Code)>0 THEN LEFT(TblCode.Code, CHARINDEX('.', TblCode.Code)-1)
ELSE TblCode.Code
END IN (#parCode)
)
The first clause makes exact match so for your example matches C73.0
The second clause matches characters before the dot character so it would get values C79.0, C79.1, C79.2 etc
Warning: Filtering using expressions would invalidate the use of an index on TblCode.Code

How to create a correct filter string with OR and AND operators for django?

My app has a frontend on vue.js and backend on django rest framework. I need to do a filter string on vue which should do something like this:
((status=closed) | (status=canceled)) & (priority=middle)
but got an error as a response
["Invalid querystring operator. Matched: ') & '."]
After encoding my string looks like this:
?filters=((status%3D%D0%97%D0%B0%D0%BA%D1%80%D1%8B%D1%82)%20%7C%20(status%3D%D0%9E%D1%82%D0%BA%D0%BB%D0%BE%D0%BD%D0%B5%D0%BD))%20%26%20(priority%3D%D0%A1%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D0%B9)
which corresponds to
?filters=((status=closed)|(status=canceled))&(priority=middle)
How should look a correct filter string for django?
I have no problem if statement includes only | or only &. For example filter string like this one works perfect:
?filters=(status%3D%D0%97%D0%B0%D0%BA%D1%80%D1%8B%D1%82)%20%7C%20(status%3D%D0%9E%D1%82%D0%BA%D0%BB%D0%BE%D0%BD%D0%B5%D0%BD)
a.k.a. ?filters=(status=closed)|(status=canceled). But if i add an & after it and additional brackets to specify the order of conditions calculation it fails with an error.
I also tried to reduce usage of brackets and had string like this (as experiment):
?filters=(status%3D%D0%97%D0%B0%D0%BA%D1%80%D1%8B%D1%82%20%7C%20status%3D%D0%9E%D1%82%D0%BA%D0%BB%D0%BE%D0%BD%D0%B5%D0%BD)
a.k.a. ?filters=(status=closed | status=canceled). This one doesn't work - get neither error nor the data.
I need to have a mixed results in my case: both statuses (closed and canceled) and priority=middle, but a string format isn't correct. Please explain, which format would be Ok?
That doesn't look like a very uri friendly syntax you're trying to use there.
Try doing this instead:
?status[]=closed&status[]=cancelled&priority=middle
Then use request.GET.getlist('status[]') to get back the list and use the values for logical OR queryset filtering:
qs = qs.filter(status__in=request.GET.getlist('status[]', [])
and then add any additional filtering which works as logical AND.
If you're using axios, it should automatically format js status url param into proper format.

PostgreSQL - removing trailing comma before WHERE from query string

I have an API that takes a PATCH request with one or more parameters and build a query string that looks like this
UPDATE ${table} SET ${param1}${param2}${param3} WHERE id=${id}
problem is if I place commas inside params or in the final query, a request with a single parameter breaks the query
UPDATE ${table} SET ${param1}, WHERE id=${id}
or
UPDATE ${table} SET ${param1},, WHERE id=${id}
how do I remove commas before WHERE?
You could join all the params together, but make sure that the input is sanitized for sql injection. Assuming they're already in a list like
params = [param1, param2, param3];
paramsStr = params.join(", ");
example:
["abc='def'", "xyz=123"].join(',')
#outputs:
'abc=\'def\',xyz=123'
And then use the paramsStr in your query template. With this simple trick you avoid having to deal with trailing / leading commas
UPDATE ${table} SET ${paramsStr} WHERE id=${id}

SQL: Find and Replace with SQL?

I have a MySQL InnoDB database.
I have a column my in 'article' table called url that needs to be updated.
Stored in article.url =
/blog/2010/article-name
/blog/1998/the-article-name
/blog/...
I need to change /blog/ to /news/. (E.g. now article.url = '/news/...')
What is the SQL needed to replace "/blog/" with "/news/" in the article.url column?
update url
set article = replace(article, '/blog/', '/news/')
where article like '/blog/%'
If every url starts with "/blog/" and you don't want to change anything except the prefix, then you can just use substring() and concat() instead of replace():
update article
set url = concat('/news/',substring(url,7))
where url like '/blog/%';
I recently wanted to replace a string within MySQL on the fly, but the field could contain 2 items. So I wrapped a REPLACE() within a REPLACE(), such as:
REPLACE(REPLACE(field_name, “what we are looking for”, “replace first instance”),
“something else we are looking for”, “replace second instance”)
This is the syntax I used to detect a boolean value:
REPLACE(REPLACE(field, 1, “Yes”), 0, “No”)
Hope this helps!