PostgreSQL: using strings in SQL subquery text in a function - postgresql

I'm using the pgr_drivingDistance function that requires a SQL subquery as text like so:
pgr_drivingDistance(
'SELECT id, source, target, cost, reverse_cost FROM edges', start_vid, dist, true
)
I would like to subset the edges in the edges table with a where clause like so:
pgr_drivingDistance(
'SELECT id, source, target, cost, reverse_cost FROM edges WHERE col = 'some_string'', start_vid, dist, true
)
The problem is I cannot use single quotes in this case for the string. I tried to escape the quotes of the string with ''', backslash, $$ notations without success.
Is there a way to do this?

There's various ways to escape single quotes (apostrophes) in Postgres string literals:
"To include a single-quote character within a string constant, write two adjacent single quotes"
pgr_drivingDistance('SELECT … WHERE col = ''some_string'' ', start_vid, dist, true)
"A single quote can be included in an escape string by writing \', in addition to the normal way of ''."
pgr_drivingDistance(e'SELECT … WHERE col = \'some_string\' ', start_vid, dist, true)
"Inside the dollar-quoted string, single quotes can be used without needing to be escaped"
pgr_drivingDistance($$SELECT … WHERE col = 'some_string'$$, start_vid, dist, true)

Related

How can I return the first 3 characters after every comma in a string in TSQL

I have a string that I need to seperate into values seperated by commas. I have achieved this part with the below REPLACE statement:
declare #mc varchar(200)
declare #mc1 varchar(200)
select #mc = 'FRED&#g4;&#4g;MARY&#g4;&#4g;BILL&#g4;&#4g;TIMOTHY&#g4;&#4g;JOHNATHAN'
select #mc1 = REPLACE(#mc, '&#g4;&#4g;',', ')
The replace returns a string 'FRED, MARY, BILL, TIMOTHY, JOHNATHAN'
I then want to have another variable that will return the first 3 characters of each value before the commas, so the above string would be returned as:
'FRE, MAR, TIM, JOH'
Anyone know how I can achieve this?
Also happy for this to be done directly to the original #mc variable
ON SQL Server 2017+ you can make use of openJson to split the string into manageble segments and then string_agg to assemble the desired result:
declare #mc varchar(100)='FRED&#g4;&#4g;MARY&#g4;&#4g;BILL&#g4;&#4g;TIMOTHY&#g4;&#4g;JOHNATHAN'
select String_Agg(v, ', ')
from (select #mc)x(s)
cross apply (
select Left(j.[value],3) v, Convert(tinyint,j.[key]) Seq
from OpenJson(Concat('["',replace(s,';', '","'),'"]')) j
where Convert(tinyint,j.[key]) % 2 = 0
)j;
Demo Fiddle

postgresql replace symbol for store function variable?

I find '#' can replace some string in posgresql like:
SELECT
'Record #' || i
FROM
generate_series(1, 1000) i;
The symbol '#' can replace the by i, in this SQL commands.
I want to do similar like this for function like
SELECT lo_unlink('#') || i
From
SELECT picture i FROM image where belong_to = 254;
Of course '#' there is grammar error around '#', I just want to know any placehold grammar or symbol can work in function parameter like it replace string mark '#'
The symbol # is not replaced, you are concatenating a number to a string containing this symbol.
This concatenation can occur anywhere, including when building a function parameter:
SELECT lo_unlink('#' || i)
From
SELECT picture i FROM image where belong_to = 254;
which, if i is number 1, will create (and call) lo_unlink('#1')
so you may want to use i directly:
SELECT lo_unlink(i)
From
SELECT picture i FROM image where belong_to = 254;
which, if i is number 1, will create (and call) lo_unlink(1)

Postgresql add double quote to string while COPY-TO

I'm writting a file from a DB-Procedure.
I need to export a string value and I have to add double quotes in front and back of the string.
exp: "TEST".
I use the following code but the result is always like """TEST""" and I don't know why.
EXECUTE 'COPY (
SELECT concat(''"'', x.text1, ''"'')
FROM my_table x
) to ''' || dump_path || ''' WITH (FORMAT csv, DELIMITER '','', ENCODING ''WIN1252'')';

How to find/replace weird whitespace in string

I find in my sql database string whit weird whitespace which cannot be replace like REPLACE(string, ' ', '') RTRIM and cant it even find with string = '% %'. This space is even transfered to new table when using SELECT string INTO
If i select this string in managment studio and copy that is seems is normal space and when everything is works but cant do nothing directly from database. What else can i do? Its some kind of error or can i try some special character for this?
First, you must identify the character.
You can do that by using a tally table (or a cte) and the Unicode function:
The following script will return a table with two columns: one contains a char and the other it's unicode value:
DECLARE #Str nvarchar(100) = N'This is a string containing 1 number and some words.';
with Tally(n) as
(
SELECT TOP(LEN(#str)) ROW_NUMBER() OVER(ORDER BY ##SPID)
FROM sys.objects a
--CROSS JOIN sys.objects b -- (unremark if there are not enough rows in the tally cte)
)
SELECT SUBSTRING(#str, n, 1) As TheChar,
UNICODE(SUBSTRING(#str, n, 1)) As TheCode
FROM Tally
WHERE n <= LEN(#str)
You can also add a condition to the where clause to only include "special" chars:
AND SUBSTRING(#str, n, 1) NOT LIKE '[a-zA-Z0-9]'
Then you can replace it using it's unicode value using nchar (I've used 32 in this example since it's unicode "regular" space:
SELECT REPLACE(#str, NCHAR(32), '|')
Result:
This|is|a|string|containing|1|number|and|some|words.

Need help understanding quotation marks in a SQL string to be passed to linked server.

I need to build a SQL statement to be submitted on a linked server. The statement makes use of #parameters and case statements which contain quotation marks.
I found this Microsoft article 'How to pass a variable', which seemed ideal, however I am not able to get everything going. It seems that the linked server is not enabled for the final and neatest suggestion of calling Sp_executesql, so I have been trying the first two examples.
To start with, here is a cut down example of my SQL statement on its own:
SELECT *,
CASE WHEN FLDA = 'ABC' THEN 'DEF' ELSE 'ABC' END AS COL1
FROM MYTABLE
WHERE FLDB = #PARM
1, I can get the query to work when excluding the CASE statement:
DECLARE #TSQL NVARCHAR(4000), #PARM NVARCHAR(10)
SET #PARM = 'ABC'
SET #TSQL = 'SELECT * FROM OPENQUERY(MYLINKEDSERVER, ''
SELECT *
FROM MYTABLE
WHERE FLDA = '''''+#PARM+''''''')'
EXEC (#TSQL)
However I don't understand why I require 5 quotes before #PARM and then 7(!) after it? When coding SQL statements in a string in previous languages just 2 quotations together acted as a single. So why 5 and 7?
2, I can't get the SQL to work at all when attempting to add the CASE statement. I have tried all combinations of 2,3,4 quotations but to no avail: Do I again need a certain amount of opening quotes and then a different amount of closing quotes?
DECLARE #TSQL NVARCHAR(4000), #PARM NVARCHAR(10)
SET #PARM = 'ABC'
SET #TSQL = 'SELECT * FROM OPENQUERY(MYLINKEDSERVER, ''
SELECT *,
CASE WHEN FLDA = ''ABC'' THEN ''DEF'' ELSE ''ABC'' END AS COL1
FROM MYTABLE
WHERE FLDA = '''''+#PARM+''''''')'
EXEC (#TSQL)
Any help greatly appreciated!
Cheers
Mark
my first question was why do I need 5 and 7 quotes, so there was no error message there, but I get the point that I could have listed some of the errors seen when I was getting the incorrect number of quotes.
However the tip to use Print was very useful, so thank you all for that!
So it transpires that I do indeed require a pair of
quotes where a single quote is required. However, as I am creating a SQL string within a string, I need to double that again. So I first need to end my string with a single quote and then add 4 quotes to create the double quote required to proceed the variable - hence 5. And likewise, I need 4 quotes to get a pair of quotes following the variable, another pair of quotes for the quote to end the statement and then a final one to wrap around the end bracket of the OPENQUERY command....I hope that sort of reads correct!
So:
WHERE FLDA = '''''+#PARM+''''''')'
Printed as:
WHERE FLDA = ''ABC''')
And for my CASE statement, I required 4 set of quotes, to equate to 2. So:
CASE WHEN FLDA = ''''ABC'''' THEN ''''DEF'''' ELSE ''''ABC'''' END AS COL1
Printed as:
CASE WHEN FLDA = ''ABC'' THEN ''DEF'' ELSE ''ABC'' END AS COL1