Find Substring - SQL - sql

I need to find a substring that is in a text field that is actually partially xml. I tried converting it to xml and then use the .value method but to no avail.
The element(substring) I am looking for is a method name that looks like this:
AssemblyQualifiedName="IPMGlobal.CRM2011.IPM.CustomWorkflowActivities.ProcessChildRecords,
where the method at the end "ProcessChildRecords" could be another name such as "SendEmail". I know I can use the "CustomWorkflowActivities." and the , (comma) to find the substring (method name) but not sure how to accomplish it. In addition, there may be more that one instance listed of the **"CustomWorkflowActvities.<method>"**
Some Clarifications:
Below is my original query. It returns that first occurrence in each row but no additional. For example I might have in the string '...IPM.CustomWorkflowActivities.ProcessChildRecords...' and
'...IPM.CustomWorkflowActivities.GetworkflowContext...'
The current query only returns Approve Time Process,
ipm_mytimesheetbatch,
ProcessChildRecords
SELECT WF.name WFName,
(
SELECT TOP 1 Name
FROM entity E
WHERE WF.primaryentity = E.ObjectTypeCode
) Entity,
Convert(xml, xaml) Xaml,
SUBSTRING(xaml, Charindex('CustomWorkflowActivities.', xaml) + Len('CustomWorkflowActivities.'), Charindex(', IPMGlobal.CRM2011.IPM.CustomWorkflowActivities, Version=1.0.0.0', xaml) - Charindex('CustomWorkflowActivities.', xaml) - Len('CustomWorkflowActivities.'))
FROM FilteredWorkflow WF
WHERE 1 = 1
AND xaml LIKE '%customworkflowactivities%'
AND statecodename = 'Activated'
AND typename = 'Definition'
ORDER BY NAME

If you are using Oracle you could use REGEXP function:
WITH cte(t) as (
SELECT 'AssemblyQualifiedName="IPMGlobal.CRM2011.IPM.CustomWorkflowActivities.ProcessChildRecords,' FROM dual
)
SELECT t,
regexp_replace(t, '.*CustomWorkflowActivities.(.+)\,.*', '\1') AS r
FROM cte;
DBFiddle Demo
SQL Server:
WITH cte(t) as (
SELECT 'AssemblyQualifiedName="IPMGlobal.CRM2011.IPM.CustomWorkflowActivities.ProcessChildRecords,asfdsa'
)
SELECT t,SUBSTRING(t, s, CHARINDEX(',', t, s)-s)
FROM (SELECT t, PATINDEX( '%CustomWorkflowActivities.%', t) + LEN('CustomWorkflowActivities.') AS s
FROM cte
) sub;
DBFiddle Demo 2

Related

Apply like function on an array is SQL Server

I am getting array from front end to perform filters according that inside the SQL query.
I want to apply a LIKE filter on the array. How to add an array inside LIKE function?
I am using Angular with Html as front end and Node as back end.
Array being passed in from the front end:
[ "Sports", "Life", "Relationship", ...]
SQL query is :
SELECT *
FROM Skills
WHERE Description LIKE ('%Sports%')
SELECT *
FROM Skills
WHERE Description LIKE ('%Life%')
SELECT *
FROM Skills
WHERE Description LIKE ('%Relationship%')
But I am getting an array from the front end - how to create a query for this?
In SQL Server 2017 you can use OPENJSON to consume the JSON string as-is:
SELECT *
FROM skills
WHERE EXISTS (
SELECT 1
FROM OPENJSON('["Sports", "Life", "Relationship"]', '$') AS j
WHERE skills.description LIKE '%' + j.value + '%'
)
Demo on db<>fiddle
As an example, for SQL Server 2016+ and STRING_SPLIT():
DECLARE #Str NVARCHAR(100) = N'mast;mode'
SELECT name FROM sys.databases sd
INNER JOIN STRING_SPLIT(#Str, N';') val ON sd.name LIKE N'%' + val.value + N'%'
-- returns:
name
------
master
model
Worth to mention that input data to be strictly controlled, since such way can lead to SQL Injection attack
As the alternative and more safer and simpler approach: SQL can be generated on an app side this way:
Select * from Skills
WHERE (
Description Like '%Sports%'
OR Description Like '%Life%'
OR Description Like '%Life%'
)
A simple map()-call on the words array will allow you to generate the corresponding queries, which you can then execute (with or without joining them first into a single string).
Demo:
var words = ["Sports", "Life", "Relationship"];
var template = "Select * From Skills Where Description Like ('%{0}%')";
var queries = words.map(word => template.replace('{0}', word));
var combinedQuery = queries.join("\r\n");
console.log(queries);
console.log(combinedQuery);

oracle double data sorting

I would like to sort the below kind of data
ms3_fldr01
ms14_fldr01
ms13_fldr01
ms13_fldp01
ms30_fldr01
ms20_fldp01
ms9_fldr01
ms14_fldp01
ms4_fldp01
ms5_fldr01
ms1_fldp01
ms3_fldr01
ms8_fldr01
In such a way that fldp01 will appear first and then fldr01 .
In first appeared data set of fldp01 first (ms) part has to be sorted ( ms1...ms10) also in fldr01 data set first (ms) part has to be sorted . Like below
ms1_fldp01
ms4_fldp01
ms13_fldp01
ms14_fldp01
ms20_fldp01
ms3_fldr01
ms5_fldr01
ms8_fldr01
ms9_fldr01
ms13_fldr01
ms14_fldr01
ms30_fldr01
I have tried in below way but that is not giving data set as per expectation.
select
server, count(*) as C
from TEST
where d_updated_date >= trunc(sysdate-4)
group by server
order by
replace(replace(server,'_fldr01'),'ms') desc,
(case when substr(server,instr(server,'_')+1)='fldp01' then 1
when substr(server,instr(server,'_')+1)='fldp02' then 2
else 0 end) desc;
Can you please help here ??
I think this will do what you want:
order by (case when server like '%_fldp%' then 1 else 2 end),
length(server),
server
(Note: I know that underscore is a special character in like but the above will still work.)
This depends on the fact that the part after the _ is fixed in length. Otherwise, you will need to do a bit more work to separate out the first component.
You can use regexp_substr:
select *
from test
order by regexp_substr(server, '_\w+'),
to_number(regexp_substr(server, '\d+'));
I would expect a solution using ordinary string functions to outperform a regex-based solution.
SELECT *
FROM yourTable
ORDER BY
LENGTH(SUBSTR(server, INSTR(server, '_') + 1)),
SUBSTR(server, INSTR(server, '_') + 1),
LENGTH(SUBSTR(server, 1, INSTR(server, '_') - 1)),
SUBSTR(server, 1, INSTR(server, '_') - 1)

Appending in middle of text in column data oracle sql

I need to append the text in middle of text .
1 EX :existing text is : "Monoclonal Anti-FLAG, Clone 6F7"
Result :"<HIDE>Monoclonal Anti-<HIDE>FLAG, Clone 6F7".
2 EX :existing text is : "Anti-100-KD subunit"
Result : "<HIDE> Anti-</HIDE>100-KD subunit"
I want to append <HIDE> tag where ever Anti and Monoclonal term is coming.
select * from table where regexp_like(colnanme, '^(Monoclonal Anti|Anti)')
Can you suggest how should i write this .for select i have written query .
The predicted certain regular expression solution.
-- Start test data
with test_data as
(select 'Monoclonal Anti-FLAG, Clone 6F7' as test_string from dual union all
select 'Anti-100-KD subunit' from dual)
-- End test data
select test_string,
REGEXP_REPLACE(test_string,'(Monoclonal Anti-|Anti-)','<HIDE>\1</HIDE>')
from test_data;
"TEST_STRING" "Result"
"Monoclonal Anti-FLAG, Clone 6F7" "<HIDE>Monoclonal Anti-</HIDE>FLAG, Clone 6F7"
"Anti-100-KD subunit" "<HIDE>Anti-</HIDE>100-KD subunit"
you could use replace and like
select replace(colname, 'Anti', '"<HIDE> Anti-</HIDE> )
from table where colname like '%Anti%'
and colname not like 'Monoclonal Anti%';
of for a combined situation you can use a case when for lead replace
select case when colname like '%Monoclonal Anti%'
then replace(colname, 'Monoclonal Anti', '"<HIDE> Monoclonal Anti-</HIDE> )
when colname like '%Anti%'
then replace(colname, 'Anti', '"<HIDE> Anti-</HIDE> )
else colname
end
from table where colname like '%Anti%';

Return a pattern multiple times

I have a column called comment that can contain a certain pattern as many as 5 times and I would like to return all of them. Here is the value I have in my colum:
oijdwe wbjcwe sbr ('JOJ.TTT.ABC', test) sdfjksj dlkfjs lkf qweiuh
('JOJ.TTT.123', test) oiiqwd m lskc qu i ('JOJ.TTT.452', test) ksd
sdfskq azx ('JOJ.TTT.ACD5', test)
I would like to return the following values: JOJ.TTT.ABC, JOJ.TTT.123, JOJ.TTT.452 and JOJ.TTT.ACD5
when using the following statement
select
regexp_substr(comment,'JOJ.T{3}.{4}',1,1)
,regexp_substr(comment,'JOJ.T{3}.{4}',1,2)
,regexp_substr(comment,'JOJ.T{3}.{4}',1,3)
,regexp_substr(comment,'JOJ.T{3}.{4}',1,4)
,regexp_substr(comment,'JOJ.T{3}.{4}',1,5)
from blabla
it works fine if the pattern is JOJ.TTT.XXX but not in case there are 4 caracters after "TTT.". I know this is because of the {4} I am using. How can I get the result I want?
Thanks
Use [^']+ to match until the next '.
select
regexp_substr(comment_,q'!JOJ.T{3}[^']+!',1,1) a,
regexp_substr(comment_,q'!JOJ.T{3}[^']+!',1,2) b,
regexp_substr(comment_,q'!JOJ.T{3}[^']+!',1,3) c,
regexp_substr(comment_,q'!JOJ.T{3}[^']+!',1,4) d,
regexp_substr(comment_,q'!JOJ.T{3}[^']+!',1,5) e
from blabla;
I have changed comment into comment_ since comment is a reserved keyword in Oracle.
While the . in the regular expression works for this purpose, it will also match things you don't want, since it is a wildcard character. Use \. to match a literal .. You can also use LEVEL and CONNECT BY so you needn't write out multiple calls to REGEXP_SUBSTR() explicitly:
WITH x AS (
SELECT 'oijdwe wbjcwe sbr (''JOJ.TTT.ABC'', test) sdfjksj dlkfjs lkf qweiuh (''JOJ.TTT.123'', test) oiiqwd m lskc qu i (''JOJ.TTT.452'', test) ksd sdfskq azx (''JOJ.TTT.ACD5'', test)' AS comment1
FROM dual
)
SELECT REGEXP_SUBSTR(comment1,'JOJ\.TTT\.[A-Z0-9]+', 1, LEVEL)
FROM x
CONNECT BY REGEXP_SUBSTR(comment1,'JOJ\.TTT\.[A-Z0-9]+', 1, LEVEL) IS NOT NULL;
See SQL Fiddle here.
It gets a little kludgier if you have multiple columns and want to return them all:
WITH x AS (
SELECT 1 AS id, 'oijdwe wbjcwe sbr (''JOJ.TTT.ABC'', test) sdfjksj dlkfjs lkf qweiuh (''JOJ.TTT.123'', test) oiiqwd m lskc qu i (''JOJ.TTT.452'', test) ksd sdfskq azx (''JOJ.TTT.ACD5'', test)' AS comment1
FROM dual
UNION ALL
SELECT 2 AS id, 'oijdwe wbjcwe sbr (''JOJ.TTT.ABC'', test) sdfjksj dlkfjs lkf qweiuh (''JOJ.TTT.123'', test) oiiqwd m lskc qu i (''JOJ.TTT.452'', test) ksd sdfskq azx (''JOJ.TTT.ACD5'', test)' AS comment1
FROM dual
)
SELECT id, REGEXP_SUBSTR(comment1,'JOJ\.TTT\.[A-Z0-9]+', 1, LEVEL)
FROM x
CONNECT BY REGEXP_SUBSTR(comment1,'JOJ\.TTT\.[A-Z0-9]+', 1, LEVEL) IS NOT NULL
AND PRIOR id = id
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL;
See SQL Fiddle here. Without the PRIOR clauses Oracle will return a cross join of the values of id and of comment1.
By the way, COMMENT is an Oracle reserved word and the above queries did not work in 11g r2 with a column named comment. That is why I used comment1 instead.
Alternately, you could use [^'']+ instead of [A-Z0-9]+ but given your example data I'm not sure that's what you want.
I found how to fix it
select
regexp_substr(comment,'JOJ.T[^'']+',1,1)
,regexp_substr(comment,'JOJ.T[^'']+',1,2)
,regexp_substr(comment,'JOJ.T[^'']+',1,3)
,regexp_substr(comment,'JOJ.T[^'']+',1,4)
,regexp_substr(comment,'JOJ.T[^'']+',1,5)
from blabla

how to get all the fields in sql server 2008

I want to get all the fields from the table which i select in the query even if the fields contains no value(the value null or empty). the following is the query i have written.
SELECT (
SELECT T1.[CarrierCode_Destination] AS '#CarrierCode_Destination',
T1.[CarrierCode_Destination_Address] AS
'#CarrierCode_Destination_Address',
T1.[CarrierCode_Destination_Address1] AS
'#CarrierCode_Destination_Address1',
T1.[CarrierCode_Destination_Address2] AS
'#CarrierCode_Destination_Address2',
T1.[CIMtrek_RegContact] AS '#CIMtrek_RegContact',
T1.[CIMtrek_CarrierContact] AS '#CIMtrek_CarrierContact',
[T1].[CIMtrek_AdditionalContacts] AS
'#CIMtrek_AdditionalContacts'
FROM (
SELECT CD.[CIMtrek_DestinationName]
CarrierCode_Destination,
CD.[CIMtrek_DestinationAdd]
CarrierCode_Destination_Address,
CD.[CIMtrek_DestinationAdd_1]
CarrierCode_Destination_Address1,
CD.[CIMtrek_DestinationAdd_2]
CarrierCode_Destination_Address2,
CD.[CIMtrek_RegContact] CIMtrek_RegContact,
CD.[CIMtrek_CarrierContact] CIMtrek_CarrierContact,
CD.[CIMtrek_AdditionalContacts]
CIMtrek_AdditionalContacts
FROM CIMtrek_SystemTable_DatawareHouse CD
WHERE LEN(
LTRIM(
RTRIM(ISNULL(LTRIM(RTRIM(CD.[CIMtrek_DestinationName])), ''))
)
) != 0
) AS T1
FOR XML PATH('Record'),
TYPE
) FOR XML PATH('CarrierCode_Destination'),
TYPE
the results i get is
<CarrierCode_Destination>
<Record CarrierCode_Destination="8S - San Fran" CarrierCode_Destination_Address="SAN FRANCISCO - Redistribution" CarrierCode_Destination_Address1="4025 Whipple Road, " CarrierCode_Destination_Address2="Union City CA 94587" CIMtrek_RegContact="RDC San Francisco" />
<Record CarrierCode_Destination="8G - St Louis" CarrierCode_Destination_Address="ST. LOUIS - Redistribution" CarrierCode_Destination_Address1="126 Enterprise Drive, " CarrierCode_Destination_Address2="Wentzville MO 63385" CIMtrek_RegContact="RDC St Louis" />
<Record CarrierCode_Destination="V8 PHO/CYPR/CUST/TL  " />
</CarrierCode_Destination>
but i want all the fields which are selected in the query. If you see the result it gives me the fields which are having value and omits the fields which don't have values.
how to do this, Please help.
Best Regards
If you use isnull() statements for each column you are selecting and convert null values to empty strings it should force the attributes to be generated for all columns. You may or may not also need to add rtrim() statements like I show below depending on if you have a datatype that is going to return a fixed size string:
SELECT (
SELECT rtrim(isnull(T1.[CarrierCode_Destination],'')) AS '#CarrierCode_Destination',
rtrim(isnull(T1.[CarrierCode_Destination_Address],'')) AS
'#CarrierCode_Destination_Address',
rtrim(IsNull(T1.[CarrierCode_Destination_Address1],'')) AS
'#CarrierCode_Destination_Address1',
rtrim(IsNull(T1.[CarrierCode_Destination_Address2],'')) AS
'#CarrierCode_Destination_Address2',
rtrim(IsNull(T1.[CIMtrek_RegContact],'')) AS '#CIMtrek_RegContact',
rtrim(IsNull(T1.[CIMtrek_CarrierContact],'')) AS '#CIMtrek_CarrierContact',
rtrim(IsNull([T1].[CIMtrek_AdditionalContacts],'')) AS
'#CIMtrek_AdditionalContacts'
FROM (
SELECT CD.[CIMtrek_DestinationName]
CarrierCode_Destination,
CD.[CIMtrek_DestinationAdd]
CarrierCode_Destination_Address,
CD.[CIMtrek_DestinationAdd_1]
CarrierCode_Destination_Address1,
CD.[CIMtrek_DestinationAdd_2]
CarrierCode_Destination_Address2,
CD.[CIMtrek_RegContact] CIMtrek_RegContact,
CD.[CIMtrek_CarrierContact] CIMtrek_CarrierContact,
CD.[CIMtrek_AdditionalContacts]
CIMtrek_AdditionalContacts
FROM CIMtrek_SystemTable_DatawareHouse CD
WHERE LEN(
LTRIM(
RTRIM(ISNULL(LTRIM(RTRIM(CD.[CIMtrek_DestinationName])), ''))
)
) != 0
) AS T1
FOR XML PATH('Record'),
TYPE
) FOR XML PATH('CarrierCode_Destination'),
TYPE
That worked for me when I tested it out but if you are also having issues with empty values not generating attributes you can first force all the empty values to be returned as NULL from the select against your original data table using NULLIF()
SELECT (
SELECT rtrim(isnull(T1.[CarrierCode_Destination],'')) AS '#CarrierCode_Destination',
rtrim(isnull(T1.[CarrierCode_Destination_Address],'')) AS
'#CarrierCode_Destination_Address',
rtrim(IsNull(T1.[CarrierCode_Destination_Address1],'')) AS
'#CarrierCode_Destination_Address1',
rtrim(IsNull(T1.[CarrierCode_Destination_Address2],'')) AS
'#CarrierCode_Destination_Address2',
rtrim(IsNull(T1.[CIMtrek_RegContact],'')) AS '#CIMtrek_RegContact',
rtrim(IsNull(T1.[CIMtrek_CarrierContact],'')) AS '#CIMtrek_CarrierContact',
rtrim(IsNull([T1].[CIMtrek_AdditionalContacts],'')) AS
'#CIMtrek_AdditionalContacts'
FROM (
SELECT NullIF(CD.[CIMtrek_DestinationName],'')
CarrierCode_Destination,
NullIF(CD.[CIMtrek_DestinationAdd],'')
CarrierCode_Destination_Address,
NullIF(CD.[CIMtrek_DestinationAdd_1],'')
CarrierCode_Destination_Address1,
NullIF(CD.[CIMtrek_DestinationAdd_2],'')
CarrierCode_Destination_Address2,
NullIF(CD.[CIMtrek_RegContact],'') CIMtrek_RegContact,
NullIF(CD.[CIMtrek_CarrierContact],'') CIMtrek_CarrierContact,
NullIF(CD.[CIMtrek_AdditionalContacts],'')
CIMtrek_AdditionalContacts
FROM CIMtrek_SystemTable_DatawareHouse CD
WHERE LEN(
LTRIM(
RTRIM(ISNULL(LTRIM(RTRIM(CD.[CIMtrek_DestinationName])), ''))
)
) != 0
) AS T1
FOR XML PATH('Record'),
TYPE
) FOR XML PATH('CarrierCode_Destination'),
TYPE
I normally use the following syntax:
SELECT *
FROM TABLE_NAME
WHERE FIELD_NAME = "CRITERIA"