My stored procedure receives a parameter which is a comma-separated string:
DECLARE #review_status varchar(200)
SET #review_status='CANCELLED,INSPECTED,REJECTED,UNASSIGNED'
I use this variable with LIKE Operator, when value without comma then perfect but it comes with comma then unable to handle.
Now i use this statement
SELECT * FROM tblReview WHERE
review_status LIKE '%' + #review_status + '%'
I need to make from it this statement
SELECT * FROM tblReview WHERE
review_status LIKE '%CANCELLED%' OR --Pass #review_status
review_status LIKE '%INSPECTED%' OR
review_status LIKE '%REJECTED%'.....
What is the best practice for doing this?
You could use a string splitter to do this. Read this article for one of the fastest splitter there is.
Then you need to use the IN operator to do the filtering:
SELECT *
FROM tblReview
WHERE review_status IN(
SELECT item FROM dbo.DelimitedSplit8K(#review_status,',')
)
Since you're using LIKE, you may want to do JOIN instead of IN:
SELECT *
FROM tblReview t
INNER JOIN dbo.DelimitedSplit8K(#review_status, ',') s
ON t.review_status LIKE '%' + s.Item + '%'
Try to first convert varchar with commas to a table as described here http://blogs.msdn.com/b/amitjet/archive/2009/12/11/sql-server-comma-separated-string-to-table.aspx. Then, use the following:
CREATE TABLE #allPattern (
pattern NVARCHAR(max)
);
INSERT INTO #allPattern VALUES ('%CANCELLED%'), ('%INSPECTED%'), ('%REJECTED%');
SELECT t.* FROM tblReview t JOIN #allPattern a ON (t.review_status LIKE a.pattern);
You can add the pre- and trailing comma to yous string, and then use CHARINDEX().
SET #review_status=',CANCELLED,INSPECTED,REJECTED,UNASSIGNED,'
SELECT * FROM tblReview WHERE
charindex(','+review_status+',', '#review_status') >0
Commas at the beginning and at the end of the string are used to make an exact string finding possible - for example, if you have two statuses - one called CAN and the second called CANCELLED, charindex without side commas will find them both.
It's the simplest way, but not the one with the best performance, so don't use it on long CSVs.
Related
İ have a problem with contains function, when i search with like '%ZAM%' operator, it finds all word that contains ZAM like ZAMANLAMA AZAMI ZAM and etc.. but when I use fts index contains function, it just find ZAM ZAMANLAMA but it doesnt find AZAMI or 123ZAM789. I have also tried CONTAINS (YourColumn, ' "ZAM" ' ) but it doesn't work. Please help me , fts is very fast but it could not find all contains like '%%' operator what should I do ?
You can use "*" before in contain syntax same as like operator . but you need to use double quote before and after the search string.
Try this query once.
SELECT *
FROM YourTable
WHERE CONTAINS(YourColumn,'"*ZAM*"');
(OR)
select * from YourTable where YourColumn like '%ZAM%'
I need to store the text of all of the stored procedures in a database into an XML data type. When I use, FOR XML PATH, the text within in the stored procedure contains serialized data characters like
and
for CRLF and ", etc. I need the text to stored in the xml structure without these characters because the text will need to be used to recreate the stored procedure.
This is the query that I use for FOR XML PATH:
SELECT
[View].name AS "#VName", [Module].definition AS "#VDefinition"
FROM
sys.views AS [View]
INNER JOIN
sys.sql_modules AS [Module] ON [Module].object_id = [View].object_id
FOR XML PATH ('View'), TYPE
I read that I should use CDATA for the text using FOR XML EXPLICIT. However, the output of the when I run the following query and view the XML data, it contains those characters also. I need the text to be in plain text without these characters.
This is my query:
SELECT
1 AS Tag,
0 AS Parent,
NULL AS [Database1!1],
NULL AS [StoredProcedure!2!VName],
NULL AS [StoredProcedure!2!cdata]
UNION ALL
SELECT
2 AS Tag,
1 AS Parent,
NULL,
[StoredProcedure].name as [StoredProcedure!2!!CDATA],
[Module].definition as [StoredProcedure!2!!CDATA]
FROM
sys.procedures AS [StoredProcedure]
INNER JOIN
sys.sql_modules [Module] ON [StoredProcedure].object_id = [Module].object_id
WHERE
[StoredProcedure].name NOT LIKE '%diagram%'
FOR XML EXPLICIT
How can I store the text of a the stored procedures that is in plain text? Or when I parse the xml data type to recreate the stored procedure can I deserialize it so that it does not have those characters?
Ideally, I would like to use FOR XML PATH but if that is not possible I will use FOR XML EXPLICIT.
If you want to store data with special characters within XML, there are two options (plus a joke option)
escaping
CDATA
just to mention: Convert everything to base64 or similar would work too :-)
The point is: You do not need this!
The only reason for CDATA (at least for me) is manually created content (copy'n'paste or typing). Whenever you build your XML automatically, you should rely on the implicitly applied escaping.
Why does it bother you, how the data is looking within the XML?
If you read this properly (not with SUBSTRING or other string based methods), you will get it back in the original look.
Try this:
DECLARE #TextWithSpecialCharacters NVARCHAR(100)=N'€ This is' + CHAR(13) + 'strange <ups, angular brackets! > And Ampersand &&&';
SELECT #TextWithSpecialCharacters FOR XML PATH('test');
returns
€ This is
strange <ups, angular brackets! > And Ampersand &&&
But this...
SELECT (SELECT #TextWithSpecialCharacters FOR XML PATH('test'),TYPE).value('/test[1]','nvarchar(100)');
...returns
€ This is
strange <ups, angular brackets! > And Ampersand &&&
Microsoft decided not even to support this with FOR XML (except EXPLICIT, which is a pain in the neck...)
Read two related answers (by me :-) about CDATA)
https://stackoverflow.com/a/38547537/5089204
https://stackoverflow.com/a/39034049/5089204 (with further links...)
When I use, FOR XML PATH, the text within in the stored procedure contains serialized data characters like
and
for CRLF and ", etc.
Yes, because that's how XML works. To take a clearer example, suppose your sproc contained this text:
IF #someString = '<' THEN
then to store it in XML, there must be some kind of encoding applied, since you can't have a bare < in the middle of your XML (I hope you can see why).
The real question is then not 'how do I stop my text being encoded when I store it as XML', but rather (as you guess might be the case):
Or when I parse the xml data type to recreate the stored procedure can I deserialize it so that it does not have those characters?
Yes, this is the approach you should be looking at.
You don't how us how you're getting your text out of the XML at the moment. The key thing to remember is that you can't (or rather shouldn't) treat XML as 'text with extra bits' - you should use methods that understand XML.
If you're extracting the text in T-SQL itself, use the various XQuery options. If in C#, use any of the various XML libraries. Just don't do a substring operation and expect that to work...
An example, if you are extracting in T-SQL:
DECLARE #someRandomText nvarchar(max) = 'I am some arbitrary text, eg a sproc definition.
I contain newlines
And arbitrary characters such as < > &
The end.';
-- Pack into XML
DECLARE #asXml xml = ( SELECT #someRandomText FOR XML PATH ('Example'), TYPE );
SELECT #asXml;
-- Extract
DECLARE #textOut nvarchar(max) = ( SELECT #asXml.value('.', 'nvarchar(max)') ) ;
SELECT #textOut;
But you can find many many tutorials on how to get values out of xml-typed data; this is just an example.
SELECT
1 as Tag,
0 as Parent,
[View].name AS 'StoredProcedure!1!Name',
[Module].definition AS 'StoredProcedure!1!Definition!cdata'
FROM sys.views AS [View]
INNER JOIN sys.sql_modules AS [Module] ON [Module].object_id = [View].object_id
FOR XML EXPLICIT
Sample of the output from Adventureworks2012:
<StoredProcedure Name="vStoreWithContacts">
<Definition><![CDATA[
CREATE VIEW [Sales].[vStoreWithContacts] AS
SELECT
s.[BusinessEntityID]
,s.[Name]
,ct.[Name] AS [ContactType]
,p.[Title]
,p.[FirstName]
,p.[MiddleName]
,p.[LastName]
,p.[Suffix]
,pp.[PhoneNumber]
,pnt.[Name] AS [PhoneNumberType]
,ea.[EmailAddress]
,p.[EmailPromotion]
FROM [Sales].[Store] s
INNER JOIN [Person].[BusinessEntityContact] bec
ON bec.[BusinessEntityID] = s.[BusinessEntityID]
INNER JOIN [Person].[ContactType] ct
ON ct.[ContactTypeID] = bec.[ContactTypeID]
INNER JOIN [Person].[Person] p
ON p.[BusinessEntityID] = bec.[PersonID]
LEFT OUTER JOIN [Person].[EmailAddress] ea
ON ea.[BusinessEntityID] = p.[BusinessEntityID]
LEFT OUTER JOIN [Person].[PersonPhone] pp
ON pp.[BusinessEntityID] = p.[BusinessEntityID]
LEFT OUTER JOIN [Person].[PhoneNumberType] pnt
ON pnt.[PhoneNumberTypeID] = pp.[PhoneNumberTypeID];
]]></Definition>
</StoredProcedure>
<StoredProcedure Name="vStoreWithAddresses">
<Definition><![CDATA[
CREATE VIEW [Sales].[vStoreWithAddresses] AS
SELECT
s.[BusinessEntityID]
,s.[Name]
,at.[Name] AS [AddressType]
,a.[AddressLine1]
,a.[AddressLine2]
,a.[City]
,sp.[Name] AS [StateProvinceName]
,a.[PostalCode]
,cr.[Name] AS [CountryRegionName]
FROM [Sales].[Store] s
INNER JOIN [Person].[BusinessEntityAddress] bea
ON bea.[BusinessEntityID] = s.[BusinessEntityID]
INNER JOIN [Person].[Address] a
ON a.[AddressID] = bea.[AddressID]
INNER JOIN [Person].[StateProvince] sp
ON sp.[StateProvinceID] = a.[StateProvinceID]
INNER JOIN [Person].[CountryRegion] cr
ON cr.[CountryRegionCode] = sp.[CountryRegionCode]
INNER JOIN [Person].[AddressType] at
ON at.[AddressTypeID] = bea.[AddressTypeID];
]]></Definition>
As you note there are no
/
/ "/ etc and NewLine characters is represented as new line
I have following existing code in one of the stored procedures to all delimiter / between error messages encounters in the validations:
;with delimiting_errors
(Id,
Delimited_Error_List)
as
(
select
e2.Id,
'/'
+ (select ' ' + Fn
from Customer e
where e.Id = e2.Id
for xml path(''), type
).value('substring(text()[1],2)', 'varchar(max)') as Delimited_Error
from Customer e2
group by e2.Id
)
SELECT * FROM delimiting_errors
Request you to please help me in understanding the command
value('substring(text()[1], 2)', 'varchar(max)')
I tried to search about text(), but couldn't find exact documentation for the same.
Similarly, how substring function is working only on 2 parameters in substring(text()[1], 2), which actually requires 3 parameter.
Please help me with the concept behind this command, also please help me with some resource to read about Text().
What is going on here:
.value('substring(text()[1],2)', 'varchar(max)')
value() function to extract a specific value from the XML, and convert it to a SQL Server data type, in your case to varchar(max)
substring is XQuery substring, not SQL substring, here it returns substring starting at position 2
text() function here retrieves the inner text from within the XML
[1] suffix acts as an indexer, and fetches the first result matched
For more info read XQuery Language Reference, it's like "another language" inside SQL.
.value('substring(text()[1],2)', 'varchar(max)') as Delimited_Error
You use this XML-trick to concatenate values. In the beginning you add a double space select ' ' + Fn, this must be taken away for the beginning of the return string.
So, the .value returns the "substring" (XPath-Function!) of the inner text() starting at the index 2.
Find more information here: http://wiki.selfhtml.org/wiki/XML/XSL/XPath/Funktionen
I want to select a list of items and part numbers for for each item as a string:
SELECT top 100 *
FROM ii
OUTER APPLY
(SELECT def, ( ipr.part_number + ',') as prt
FROM ipr
WHERE ii.item_id = ipr.item_id
FOR XML PATH('') ) PN
The error is:
[Error Code: 8155, SQL State: S0002] No column name was specified for
column 1 of 'PN'.
How can I fix this?
I think that your whole OUTER APPLY statement generates one XML for both default_part_number and concatenated string, which(the whole XML) doesn't have a name.
What you could try to do would be adding alias like this AS PN(TestThis).
However, I don't think that you're expecting result you're going to get. It would better if you'd give us some example data and expected output. It will be easier for us to solve your problem in that case.
The combination of XML and STUFF is funny but perfectly fitting to your needs.
First you concat your strings with the ', ' in front, then you must return your XML with ", TPYE). You must read the result with ".value()" and use STUFF to replace the first ', '.
You'll find a lot of exampels in the net...
I have a comma delimited string of keywords which I have successfully transformed into a list using a function that takes a #String and returns a TABLE(Value varchar(30))
I can now use this list in a where clause like follows:
SELECT project.*
FROM Projects project
WHERE project.title IN (SELECT * FROM dbo.ParamsToList('.net,test'))
This matches where project.title is exactly (equal to) any one of the keywords (.net or test).
What I need is to match where title is LIKE '%' + any-keyword + '%'.
One way is like this:
SELECT project.*
FROM Projects project
WHERE EXISTS
(
SELECT * FROM dbo.ParamsToList('.net,test') x
WHERE project.title LIKE '%' + x.value + '%'
)
This approach will mean you don't get the same project returned multiple times, if the project matches multiple values from the params list.
Have you tried JOINING the results of the function like this
SELECT DISTINCT project.*
FROM Projects project
INNER JOIN dbo.ParamsToList('.net,test') pl ON project.title LIKE '%' + pl.Value + '%'