patternsqlMinor
Find substrings within between 2 string fragments
Viewed 0 times
substringsfragmentswithinbetweenfindstring
Problem
I am trying to populate a view in PostGIS in Postgres 9.0 and in this view I want it to contain a substring based on 2 string positions. See below for my code.
The outcome is that it doesn't like minus numbers when using strpos. I can get it go forward 6 characters to remove the 'name="' from the returned substring but cannot remove the '"/>'.
It returns the following:
where I want it return:
Any suggestions would be greatly appreciated.
ADDITION:I have found out that if I was using 9.1 I could have used strposrev and i think the following code would have worked:
CREATE OR REPLACE VIEW vw_actions AS
SELECT ls.f_table_schema, ls.f_table_name,
(SELECT substr(ls.attribute_actions_text,
strpos(ls.attribute_actions_text, 'name="')+6,
strpos(ls.attribute_actions_text, '"/>') -
strpos(ls.attribute_actions_text, 'name="'))) AS actions
FROM layer_styles ls;The outcome is that it doesn't like minus numbers when using strpos. I can get it go forward 6 characters to remove the 'name="' from the returned substring but cannot remove the '"/>'.
It returns the following:
View SHED Database"/>where I want it return:
View SHED DatabaseAny suggestions would be greatly appreciated.
ADDITION:I have found out that if I was using 9.1 I could have used strposrev and i think the following code would have worked:
CREATE OR REPLACE VIEW vw_actions AS
SELECT ls.f_table_schema, ls.f_table_name,
(SELECT substr(ls.attribute_actions_text::text,
strpos(ls.attribute_actions_text::text, 'name="'::text)+6,
strposrev(ls.attribute_actions_text::text, '"/>'::text)+3 -
strpos(ls.attribute_actions_text::text, 'name="'::text))) AS actions
FROM layer_styles ls;Solution
Use substring() with a regular expression instead:
The dot (
Like your code, this selects the first string matching the pattern and does not look further.
Also, you don't need to make your expression a subquery, that adds nothing but overhead:
Quick test case (you should have provided):
substring(ls.attribute_actions_text FROM 'name="(.*?)"/>')The dot (
.) matches any character, *? is the non-greedy quantifier for a sequence of 0 or more matches and the parentheses (()) mark the substring to be returned.Like your code, this selects the first string matching the pattern and does not look further.
Also, you don't need to make your expression a subquery, that adds nothing but overhead:
CREATE OR REPLACE VIEW vw_actions AS
SELECT ls.f_table_schema
, ls.f_table_name
, substring(ls.attribute_actions_text FROM 'name="(.*?)"/>') AS actions
FROM layer_styles ls;Quick test case (you should have provided):
SELECT *, substring(ls.attribute_actions_text FROM 'name="(.*?)"/>')
FROM (
VALUES
('bar name="View SHED Database"/> foo')
, ('bar name="View SHED Database"/> fooname="View SHED Database"/>xx')
, ('name="buntch a bull"/> fooname="View SHED Database"/>xx')
, ('xxname="bla foo grr"/>')
, ('')
, (NULL)
) ls(attribute_actions_text)Code Snippets
substring(ls.attribute_actions_text FROM 'name="(.*?)"/>')CREATE OR REPLACE VIEW vw_actions AS
SELECT ls.f_table_schema
, ls.f_table_name
, substring(ls.attribute_actions_text FROM 'name="(.*?)"/>') AS actions
FROM layer_styles ls;SELECT *, substring(ls.attribute_actions_text FROM 'name="(.*?)"/>')
FROM (
VALUES
('bar name="View SHED Database"/> foo')
, ('bar name="View SHED Database"/> fooname="View SHED Database"/>xx')
, ('name="buntch a bull"/> fooname="View SHED Database"/>xx')
, ('xxname="bla foo grr"/>')
, ('')
, (NULL)
) ls(attribute_actions_text)Context
StackExchange Database Administrators Q#105785, answer score: 5
Revisions (0)
No revisions yet.