how to use Wildcard with `WHERE IN(' ')` statment - sql

I have a WHERE IN ('') statement, if nothing is entered, how do I select ALL?

Depend on database you are working. But you can do something like this:
-- SQLServer
DECLARE #in varchar(20) = ''
SELECT * FROM <table> WHERE (#in = '' or <field> IN (''))
-- OR
IF #in = ''
SELECT * FROM <table>
ELSE
SELECT * FROM <table> WHERE <field> IN ('')

If you want to select all values, if there is no value for a variable, then just use ISNULL function( will have an index scan):
WHERE yourField IN (ISNULL(#yourNullVariable, yourField))
Let me show an example:
DECLARE #table TABLE
(
FooDate DATETIME,
FooBar VARCHAR(50)
)
INSERT INTO #table
(
FooDate,
FooBar
)
VALUES
( GETDATE(), -- FooDate - datetime
'A' -- FooBar - varchar(50)
)
, ('2019-02-18', 'AA')
, ('2019-01-18', 'B')
, ('2019-01-18', 'BB')
DECLARE #fooVariable VARCHAR(50) = NULL
SELECT * FROM #table tbl
WHERE tbl.FooBar = ISNULL(#fooVariable, tbl.FooBar)
OUTPUT:
FooDate FooBar
2019-02-18 16:37:20.920 A
2019-02-18 00:00:00.000 AA
2019-01-18 00:00:00.000 B
2019-01-18 00:00:00.000 BB
Or use dynamic SQL( will have an index seek):
DECLARE #fooVariable VARCHAR(50) = NULL
DECLARE #sql NVARCHAR(max), #where NVARCHAR(255);
SET #sql = N'SELECT * FROM Yourtable tbl'
IF #fooVariable IS NOT NULL
BEGIN
SET #where = ' tbl.FooBar = ' + #fooVariable
SET #sql = CONCAT(#sql, #where)
END
EXEC SP_EXECUTESQL #SQL

Related

T-SQL function in Select to Only Return Columns with Values

I have a query that will return only columns with values. How do I add that to a function so I can use that with any query? Would it be a function in the where clause.
create table test1
(
s_no int not null,
name varchar(10) not null,
address varchar(10) null,
emailid varchar(100) null
)
insert into test1 (s_no, name)
values (1,'A'),(2,'B'),(3,'C')
declare #column_list varchar(8000),
#counter int
set #column_list = ''
set #counter = 0
while (Select max(colid) from syscolumns where id = object_id('test1') and isnullable= 0) > #counter
begin
select #counter = min(colid)
from syscolumns
where id = object_id('test1')
and isnullable = 0
and colid > #counter
select #column_list = #column_list + ',' + (Select name from syscolumns where id = object_id('test1') and isnullable= 0 and colid = #counter)
end
select #column_list = SUBSTRING(#column_list, 2, len(#column_list))
declare #sql varchar(8000)
select #sql = 'select ' + #column_list + ' from test1'
print #sql
exec (#sql)
SELECT * FROM [dbo].[test1]
I guess you could make a stored procedure where you provide the table name as parameter, and then build your query like you are doing already
create procedure ShowOnlyFilledColumns (#tablename varchar(100)) as
begin
set nocount on
declare #column_list varchar(8000),
#counter int
set #column_list = ''
set #counter = 0
while (Select max(colid) from syscolumns where id = object_id(#tablename) and isnullable= 0) > #counter
begin
select #counter = min(colid) from syscolumns where id = object_id(#tablename) and isnullable= 0 and colid > #counter
select #column_list = #column_list + ',' + (Select name from syscolumns where id = object_id(#tablename) and isnullable= 0 and colid = #counter)
end
select #column_list = SUBSTRING(#column_list,2,len(#column_list))
declare #sql varchar(8000)
select #sql = 'select ' + #column_list + ' from ' + #tablename
--print #sql
exec (#sql)
end
and use it like this
exec ShowOnlyFilledColumns 'test1'
See the complete example in this DBFiddle
EDIT: The OP asked how he can add joins on this
There are a few tricks to join with a stored procedure, for example in these answers
However, this won't work on this solution, because it requires to create a temp table to store the result of the procedure.
The trick looks like this
-- create a temporary table to store the results of the procedure
CREATE TABLE #Temp (
s_no int not null,
name varchar(10) not null,
address varchar(10) null,
emailid varchar(100) null
)
-- call the procedure and store the result in the temporary table
INSERT INTO #Temp
exec ShowOnlyFilledColumns 'test1'
-- now I can query the temp table, and join on it and write a where clause, and I can do whatever I want
select * from #Temp
Now, this won't work in this case, because the stored procedure can return different columns every time you run it, and to make the insert into #Temp exec ShowOnlyFilledColumns 'test1' work, the table #Temp must have the same number and type of columns as the procedure returns. And you just don't know that.

How to convert Table data to JSON value in SQL Server using column values as nodes?

Hi I'm newbie to JSON process in SQL server.
Here is my table:
DECLARE #Example TABLE
(
ThirdPartyInterfaceData VARCHAR(10)
,ThirdPartyInterfaceName VARCHAR(10)
,Name VARCHAR(512)
,Value VARCHAR(800)
)
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthID','MAMDQ1ODNJN2JMMZMWZD')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthToken','YWU5NTlhNzgxYTA1OWY4NTFkMTM4NWY4ZjM5Y2Zl')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSFrom','Venue Metro')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURL','http://www.google.com')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURLMethod','POST')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSRestAPIVersion','v1')
I want to convert my table data to JSON value in a particular manner like below:
Expected Output:
{
"ThirdPartyInterfaceData": {
"SMS":
{
"ThirdPartyInterfaceName": "PLIVO",
"SYSTEM_SMSAuthID": "MAMDQ1ODNJN2JMMZMWZD",
"SYSTEM_SMSAuthToken": "YWU5NTlhNzgxYTA1OWY4NTFkMTM4NWY4ZjM5Y2Zl",
"SYSTEM_SMSFrom": "Venue Metro",
"SYSTEM_SMSStatusMonitorURL": "http://www.google.com",
"SYSTEM_SMSStatusMonitorURLMethod": "POST",
"SYSTEM_SMSRestAPIVersion": "v1"
}
}
}
I tried something, using FOR JSON AUTO, it gives the following value:
Current Output:
[
{
"ThirdPartyInterfaceData":"SMS",
"ThirdPartyInterfaceName":"PLIVO",
"Name":"SYSTEM_SMSAuthID",
"Value":"MAMDQ1ODNJN2JMMZMWZD"
},
{
"ThirdPartyInterfaceData":"SMS",
"ThirdPartyInterfaceName":"PLIVO",
"Name":"SYSTEM_SMSAuthToken",
"Value":"YWU5NTlhNzgxYTA1OWY4NTFkMTM4NWY4ZjM5Y2Zl"
},..
..."
}
]
But my requirement is the above format, is it possible? Can anybody help me to get this.
Thanks in advance.
We can use dynamic SQL. I am deleting rows from #Example table, so if you want to use my solution and do not delete rows from main table, you have to create additional table and insert all values. It should work for multiple different values in columns ThirdPartyInterfaceData and ThirdPartyInterfaceName.
SQL Server 2016 is needed.
FIRST WAY (with WHILE loop)
DECLARE #Example TABLE
(
ThirdPartyInterfaceData VARCHAR(10)
,ThirdPartyInterfaceName VARCHAR(10)
,Name VARCHAR(512)
,Value VARCHAR(800)
)
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthID','MAMDQ1ODNJN2JMMZMWZD')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthToken','YWU5NTlhNzgxYTA1OWY4NTFkMTM4NWY4ZjM5Y2Zl')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSFrom','Venue Metro')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURL','http://www.google.com')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURLMethod','POST')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSRestAPIVersion','v1')
DECLARE #sql NVARCHAR(MAX)
DECLARE #value VARCHAR(800)
DECLARE #name VARCHAR(512)
DECLARE #ThirdPartyInterfaceData VARCHAR(10)
DECLARE #ThirdPartyInterfaceName VARCHAR(10)
DECLARE #new bit = 1 --We have to recognize when to add element ""ThirdPartyInterfaceName":"PLIVO","
DECLARE #start bit = 1 --This variable is only used in first iteration of WHILE
DECLARE #json NVARCHAR(MAX)
SET #sql = 'SELECT #json = (SELECT '
/*
We are going to delete rows from table #Example, so we can use EXISTS in WHILE
*/
WHILE EXISTS(SELECT * FROM #Example)
BEGIN
SELECT TOP 1
#new = CASE WHEN #start = 0 THEN CASE
WHEN #ThirdPartyInterfaceData IS NOT NULL AND #ThirdPartyInterfaceName IS NOT NULL
AND (#ThirdPartyInterfaceData <> ThirdPartyInterfaceData OR #ThirdPartyInterfaceName <> ThirdPartyInterfaceName)
THEN 1
ELSE 0
END
ELSE 1 END,
#ThirdPartyInterfaceData = ThirdPartyInterfaceData,
#ThirdPartyInterfaceName = ThirdPartyInterfaceName,
#name = name,
#value = value
FROM #Example
ORDER BY ThirdPartyInterfaceData, ThirdPartyInterfaceName, Name
SET #start = 0
IF #new = 1
BEGIN
SET #sql = #sql + '''' + #ThirdPartyInterfaceName + ''' AS ''ThirdPartyInterfaceData.' + #ThirdPartyInterfaceData + '.ThirdPartyInterfaceName'', '
END
/*
Adding next element into JSON
*/
SET #sql = #sql + '''' + #value + '''' + ' AS ''ThirdPartyInterfaceData.' + #ThirdPartyInterfaceData + '.' + #name + ''', '
/*
Deleting current row
*/
DELETE FROM #Example WHERE #ThirdPartyInterfaceData = ThirdPartyInterfaceData AND
#ThirdPartyInterfaceName = ThirdPartyInterfaceName AND
#name = name AND
#value = value
END
/*
Deleting last, unnecessary comma and adding ' FOR JSON PATH'
*/
SET #sql = SUBSTRING(#sql,1,LEN(#sql) - 1) + ' FOR JSON PATH)'
/*
Executing sql, setting JSON into variable
*/
EXECUTE sp_executesql #sql, N'#json nvarchar(max) OUTPUT', #json = #json OUTPUT
/*
You can do whatever you want with this variable (insert into table etc.)
*/
SELECT #json
SECOND WAY (without WHILE loop):
DECLARE #Example TABLE
(
ThirdPartyInterfaceData VARCHAR(10)
,ThirdPartyInterfaceName VARCHAR(10)
,Name VARCHAR(512)
,Value VARCHAR(800)
)
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthID','MAMDQ1ODNJN2JMMZMWZD')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSAuthToken','YWU5NTlhNzgxYTA1OWY4NTFkMTM4NWY4ZjM5Y2Zl')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSFrom','Venue Metro')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURL','http://www.google.com')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSStatusMonitorURLMethod','POST')
INSERT INTO #Example VALUES('SMS','PLIVO','SYSTEM_SMSRestAPIVersion','v1')
DECLARE #sql NVARCHAR(MAX) = 'SELECT #json = (SELECT '
DECLARE #json NVARCHAR(MAX)
SELECT
#sql = #sql + JSON_Part
FROM (SELECT
ThirdPartyInterfaceData,
ROW_NUMBER() OVER (PARTITION BY ThirdPartyInterfaceData, ThirdPartyInterfaceName ORDER BY ThirdPartyInterfaceData, ThirdPartyInterfaceName, Name) AS Number,
'''' + Value + ''' AS ''ThirdPartyInterfaceData.' + ThirdPartyInterfaceData + '.' + Name + ''',' AS JSON_Part
FROM #Example
UNION ALL
SELECT DISTINCT
ThirdPartyInterfaceData,
0 AS Number,
'''' + ThirdPartyInterfaceName + ''' AS ''ThirdPartyInterfaceData.' + ThirdPartyInterfaceData + '.ThirdPartyInterfaceName'', ' AS JSON_Part
FROM #Example) a
ORDER BY ThirdPartyInterfaceData, Number
/*
Deleting last, unnecessary comma and adding ' FOR JSON PATH)'
*/
SET #sql = SUBSTRING(#sql,1,LEN(#sql) - 1) + ' FOR JSON PATH)'
PRINT #sql
/*
Executing sql
*/
EXECUTE sp_executesql #sql, N'#json nvarchar(max) OUTPUT', #json = #json OUTPUT
SELECT #json

How to compare columns and return only 1 of them in SQL

Background: I need to write a function in T-SQL on SQL Server 2008 10.0.5869.
Here's the table I'm working on (for the sake of simplicity - I only put in 3 columns here - but I have 10 columns for the actual work):
ID | Column1 | Column2 | Column3
1 | 2014-05 | 2015-02 | 2013-04
2 | 2012-09 | 2011-02 | 2013-03
ID is varchar and Column(x) are all datetime.
My end goal is to design a function fn_CompareDate to do something like this:
select fn_CompareDate(ID) from table where ID = 1
The query above should return the latest date from Column(x)s which should be 2015-02.
I used CASE WHEN but it would be almost impossible to use it for 10 columns. Is there another way to achieve the same result?
One approach is to use apply:
select d.maxd
from table t cross apply
(select max(d) as maxd
from values ((id, column1), (id, column2), (id, column3)) as val(id, d)
where val.id = t.id
) d
where t.id = 1;
EDIT:
You can do this without values():
select d.maxd
from table t cross apply
(select max(d) as maxd
from (select id, column1 as d union all
select id, column2 union all
select id, column3 union all
select id, column4
) val
where t.id = val.id
) d
where t.id = 1;
I think the below Function serves requirment better
CREATE FUNCTION fn_CompareDate(#ID VARCHAR(10))
RETURNS DATETIME
AS
BEGIN
DECLARE #maxDate DATETIME;
SELECT #maxDate =
(SELECT Max(v)
FROM (VALUES (COLUMN1), (COLUMN2), (COLUMN3)) AS value(v))
FROM table
WHERE ID = #ID
RETURN #maxDate;
END;
Now run the below query
select dbo.fn_CompareDate(ID) from table where ID = 1
Hope you got it.
You can use dynamic sql and INFORMATION_SCHEMA.COLUMNS. It supposed to work in SQL Server 2008. Try this:
CREATE PROCEDURE sp_CompareDate
#ID int,
#tableName NVARCHAR(MAX) = 'table2', -- Your table name
#dbName NVARCHAR(MAX) = 'temp' -- Your database name
AS
BEGIN
DECLARE #maxFieldValue DATETIME
DECLARE #curFieldName NVARCHAR(MAX)
DECLARE #curFieldValue DATETIME
DECLARE #sql NVARCHAR(MAX)
DECLARE fieldCursor CURSOR FOR
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #tableName
AND TABLE_CATALOG = #dbName AND COLUMN_NAME != 'ID'
OPEN fieldCursor
FETCH NEXT FROM fieldCursor INTO #curFieldName
SET #sql = N'USE [' + #dbName + N'] SELECT #curDate=' + #curFieldName
+ N' FROM ' + #tableName + N' WHERE ID=' + CAST(#ID AS NVARCHAR)
EXEC sp_executesql #sql, N'#curDate DATETIME output', #curFieldValue output;
SET #maxFieldValue = #curFieldValue
WHILE (##FETCH_STATUS = 0)
BEGIN
SET #sql = N'USE [' + #dbName + N'] SELECT #curDate=' + #curFieldName
+ N' FROM ' + #tableName + N' WHERE ID=' + CAST(#ID AS NVARCHAR)
EXEC sp_executesql #sql, N'#curDate DATETIME output', #curFieldValue output;
FETCH NEXT FROM fieldCursor INTO #curFieldName
IF (#maxFieldValue < #curFieldValue) SET #maxFieldValue = #curFieldValue
END
CLOSE fieldCursor;
DEALLOCATE fieldCursor;
SELECT #maxFieldValue
END
Hope this helps.
I found the 2nd solution from this question works quite well for me:
Create a function similar to this:
select max(col) from
(
select column1 [col] from table where id = #id
union all
select column2 from table where id = #id
union all
select column3 from table where id = #id
)

Improve SQL Server query to convert arbitrary table to JSON

After a lot of searching and piecing together the very excellent techniques for converting result sets using the FOR XML and .nodes() commands that are around the web, I was able to create this single query (not a stored procedure) which does a reasonably good job of converting any arbitrary SQL query to a JSON array.
The query will encode each data row as a single JSON object with a leading comma.
The data rows are wrapped by brackets and the whole result set is then expected to be exported to a file.
I'd like to see if anyone out there can see ways to improve its performance?
Here's the query with a sample table:
declare #xd table (col1 varchar(max), col2 int, col3 real, colNull int)
insert into #xd
select '', null, null, null
UNION ALL select 'ItemA', 123, 123.123, null
UNION ALL select 'ItemB', 456, 456.456, null
UNION ALL select '7890', 789, 789.789, null
select '[{}'
UNION ALL
select ',{' + STUFF((
(select ','
+ '"' + r.value('local-name(.)', 'varchar(max)') + '":'
+ case when r.value('./#xsi:nil', 'varchar(max)') = 'true' then 'null'
when isnumeric(r.value('.', 'varchar(max)')) = 1
then r.value('.', 'varchar(max)')
else '"' + r.value('.', 'varchar(max)') + '"'
end
from rows.nodes('/row/*') as x(r) for xml path(''))
), 1, 1, '') + '}'
from (
-- Arbitrary query goes here, (fields go where t.* is, table where #xd t is)
select (select t.* for xml raw,type,elements XSINIL) rows
from #xd t
) xd
UNION ALL
select ']'
My biggest critique of it, is that it's insanely slow.
It currently takes about 3:30 for ~42,000 rows.
My other big critique is that it currently assumes that everything that looks like a number is a number. It doesn't try to discover column type in the least (and I'm not even sure if it can).
A final minor critique is that the first data row will have a comma up front and technically it shouldn't. To compensate for that it requires that empty JSON object in the first row that starts the JSON array.
Other critiques (preferably with solutions) invited, the only real limitation I have is that the solution be decently repeatable on many arbitrary SQL queries without having to explicitly identify the column names.
I'm using SQL Server 2012.
Thanks and to anyone else like me who was looking for a generalized SQL Results -> JSON Array converter, ENJOY!
I say if you really want to kick up performance, use metaprogramming. The example below tries this with 40,000 rows and returns results in less than a second (not counting inserting the initial 40k rows, which in this example only takes about 2 seconds). It also takes into account your data types to not enclose numbers in quotes.
declare #xd table (col1 varchar(max), col2 int, col3 real, colDate datetime, colNull int);
declare #i int = 0;
while #i < 10000 begin
set #i += 1;
insert into #xd
select '', null, null, null, null
union all select 'ItemA', 123, 123.123, getDate(), null
union all select 'ItemB', 456, 456.456, getDate(), null
union all select '7890', 789, 789.789, getDate(), null;
end;
select *
into #json_base
from (
-- Insert SQL Statement here
select * from #xd
) t;
declare #columns table (
id int identity primary key,
name sysname,
datatype sysname,
is_number bit,
is_date bit);
insert into #columns(name, datatype, is_number, is_date)
select columns.name, types.name,
case when number_types.name is not NULL
then 1 else 0
end as is_number,
case when date_types.name is not NULL
then 1 else 0
end as is_date
from tempdb.sys.columns
join tempdb.sys.types
on (columns.system_type_id = types.system_type_id)
left join (values ('int'), ('real'), ('numeric'),
('decimal'), ('bigint'), ('tinyint')) as number_types(name)
on (types.name = number_types.name)
left join (values ('date'), ('datetime'), ('datetime2'),
('smalldatetime'), ('time'), ('datetimeoffset')) as date_types(name)
on (types.name = date_types.name)
where object_id = OBJECT_ID('tempdb..#json_base');
declare #field_list varchar(max) = STUFF((
select '+'',''+' + QUOTENAME(QUOTENAME(name, '"') + ':', '''')
+ '+' + case when is_number = 1
then 'COALESCE(LTRIM('
+ QUOTENAME(name) + '),''null'')'
when is_date = 1
then 'COALESCE(QUOTENAME(LTRIM(convert(varchar(max), '
+ QUOTENAME(name) + ', 126)),''"''),''null'')'
else 'COALESCE(QUOTENAME('
+ QUOTENAME(name) + ',''"''),''null'')'
end
from #columns
for xml path('')),
1, 5, '');
create table #json_result (
id int identity primary key,
line varchar(max));
declare #sql varchar(max) = REPLACE(
'insert into #json_result '
+ 'select '',{''+{f}+''}'' '
+ 'from #json_base', '{f}', #field_list);
exec(#sql);
update #json_result
set line = STUFF(line, 1, 1, '')
where id = 1;
select '['
UNION ALL
select line
from #json_result
UNION ALL
select ']';
drop table #json_base;
drop table #json_result;
From Firoz Ansari:
CREATE PROCEDURE [dbo].[GetJSON] (
#ParameterSQL AS VARCHAR(MAX)
)
AS
BEGIN
DECLARE #SQL NVARCHAR(MAX)
DECLARE #XMLString VARCHAR(MAX)
DECLARE #XML XML
DECLARE #Paramlist NVARCHAR(1000)
SET #Paramlist = N'#XML XML OUTPUT'
SET #SQL = 'WITH PrepareTable (XMLString) '
SET #SQL = #SQL + 'AS ( '
SET #SQL = #SQL + #ParameterSQL+ ' FOR XML RAW, TYPE, ELEMENTS '
SET #SQL = #SQL + ') '
SET #SQL = #SQL + 'SELECT #XML = XMLString FROM PrepareTable '
EXEC sp_executesql #SQL, #Paramlist, #XML=#XML OUTPUT
SET #XMLString = CAST(#XML AS VARCHAR(MAX))
DECLARE #JSON VARCHAR(MAX)
DECLARE #Row VARCHAR(MAX)
DECLARE #RowStart INT
DECLARE #RowEnd INT
DECLARE #FieldStart INT
DECLARE #FieldEnd INT
DECLARE #Key VARCHAR(MAX)
DECLARE #Value VARCHAR(MAX)
DECLARE #StartRoot VARCHAR(100); SET #StartRoot = ''
DECLARE #EndRoot VARCHAR(100); SET #EndRoot = ''
DECLARE #StartField VARCHAR(100); SET #StartField = ''
SET #RowStart = CharIndex(#StartRoot, #XMLString, 0)
SET #JSON = ''
WHILE #RowStart > 0
BEGIN
SET #RowStart = #RowStart+Len(#StartRoot)
SET #RowEnd = CharIndex(#EndRoot, #XMLString, #RowStart)
SET #Row = SubString(#XMLString, #RowStart, #RowEnd-#RowStart)
SET #JSON = #JSON+'{'
-- for each row
SET #FieldStart = CharIndex(#StartField, #Row, 0)
WHILE #FieldStart > 0
BEGIN
-- parse node key
SET #FieldStart = #FieldStart+Len(#StartField)
SET #FieldEnd = CharIndex(#EndField, #Row, #FieldStart)
SET #Key = SubString(#Row, #FieldStart, #FieldEnd-#FieldStart)
SET #JSON = #JSON+'"'+#Key+'":'
-- parse node value
SET #FieldStart = #FieldEnd+1
SET #FieldEnd = CharIndex('0 SET #JSON = SubString(#JSON, 0, LEN(#JSON))
SET #JSON = #JSON+'},'
--/ for each row
SET #RowStart = CharIndex(#StartRoot, #XMLString, #RowEnd)
END
IF LEN(#JSON) > 0 SET #JSON = SubString(#JSON, 0, LEN(#JSON))
SET #JSON = '[' + #JSON + ']'
SELECT #JSON
END

how to use the NormalizeChars stored procedure inside the searchWord stored Procedure

I want to remove the diacritics from this function
ALTER PROCEDURE [dbo].[SearchWord] (#Word NVARCHAR(50),
#PageNumber INT,
#ProductsPerPage INT,
#HowManyResults INT OUTPUT)
AS
SET #Word = '%' + RTRIM(#Word) + '%';
DECLARE #Results TABLE (
ProductsId INT,
ProductsCode NVARCHAR(250),
ProductsDesc NVARCHAR(MAX),
ProductsIngredients NVARCHAR(MAX),
ProductsName NVARCHAR(250),
ProductsPhoto NVARCHAR(MAX),
ProductsPrice MONEY,
ProductsWeight2 FLOAT,
RowNumber INT)
-- Obtain the matching products
INSERT INTO #Results
SELECT DISTINCT T1.ProductsID,
T1.ProductsCode,
LOWER(T1.ProductsDesc) asProductsDesc,
T1.ProductsIngredients,
LOWER(T1.ProductsName) AS ProductsName,
T1.ProductsPhoto,
T1.ProductsPrice,
T1.ProductsWeight2,
ROW_NUMBER() OVER(ORDER BY T1.ProductsName) RowNumber
FROM (SELECT ProductsID,
ProductsCode,
LOWER(ProductsDesc) AS ProductsDesc,
ProductsIngredients,
LOWER(ProductsName) AS ProductsName,
ProductsPhoto,
ProductsPrice,
ProductsWeight2
FROM Products
WHERE ProductsName LIKE #Word) AS T1
FULL OUTER JOIN (SELECT *
FROM Products
WHERE ProductsDesc LIKE #Word) AS T2
ON T1.ProductsID = T2.ProductsID
ORDER BY T1.ProductsPrice
DELETE FROM #Results
WHERE NULLIF([ProductsName], '') IS NULL
SELECT #HowManyResults = COUNT(*)
FROM #Results
INSERT INTO #Results
SELECT DISTINCT ProductsId,
ProductsCode,
ProductsDesc,
ProductsIngredients,
LOWER(ProductsName) AS ProductsName,
ProductsPhoto,
ProductsPrice,
ProductsWeight2,
RowNumber
FROM #Results
SELECT DISTINCT ProductsId,
ProductsCode,
ProductsDesc,
ProductsIngredients,
LOWER(ProductsName) AS ProductsName,
ProductsPhoto,
ProductsPrice,
ProductsWeight2,
RowNumber
FROM #Results R
WHERE R.RowNumber > ( #PageNumber - 1 ) * #ProductsPerPage
AND R.RowNumber <= #PageNumber * #ProductsPerPage
ORDER BY R.ProductsPrice ASC
using this procedure
ALTER PROCEDURE normalizeChars
(#NAME NVARCHAR(100))
AS
BEGIN
DECLARE #TempString NVARCHAR(100)
SET #TempString = #NAME
SET #TempString = LOWER(#TempString)
SET #TempString = REPLACE(#TempString,'à', 'a')
SET #TempString = REPLACE(#TempString,'è', 'e')
SET #TempString = REPLACE(#TempString,'é', 'e')
SET #TempString = REPLACE(#TempString,'ì', 'i')
SET #TempString = REPLACE(#TempString,'ò', 'o')
SET #TempString = REPLACE(#TempString,'ù', 'u')
SET #TempString = REPLACE(#TempString,'ç', 'c')
SET #TempString = REPLACE(#TempString,'''', '')
SET #TempString = REPLACE(#TempString,'`', '')
SET #TempString = REPLACE(#TempString,'-', '')
SET #TempString = REPLACE(#TempString,'ά','α')
SET #TempString = REPLACE(#TempString,'έ','ε')
SET #TempString = REPLACE(#TempString,'ί','ι')
SET #TempString = REPLACE(#TempString,'ό','ο')
SET #TempString = REPLACE(#TempString,'ή','η')
SET #TempString = REPLACE(#TempString,'ύ','υ')
RETURN #TempString
END
on ProductsName and ProductsDesc
is it possible and how?
You say you are on Greek_CI_AI. In that case most of your mappings already happen (Only the top 3 don't).
;WITH T(col1,col2) AS
(
SELECT N'''',N'' UNION ALL
SELECT N'`',N'' UNION ALL
SELECT N'-',N'' UNION ALL
SELECT N'à',N'a' UNION ALL
SELECT N'è',N'e' UNION ALL
SELECT N'é',N'e' UNION ALL
SELECT N'ì',N'i' UNION ALL
SELECT N'ò',N'o' UNION ALL
SELECT N'ù',N'u' UNION ALL
SELECT N'ç',N'c' UNION ALL
SELECT N'ά',N'α' UNION ALL
SELECT N'έ',N'ε' UNION ALL
SELECT N'ί',N'ι' UNION ALL
SELECT N'ό',N'ο' UNION ALL
SELECT N'ή',N'η' UNION ALL
SELECT N'ύ',N'υ'
)
SELECT *
FROM T
WHERE col1<>col2 COLLATE Greek_CI_AI
Returns
col1 col2
---- ----
'
`
-
Also you don't need to use LOWER as the collation is case insensitive.
If you do need to ignore the remaining 3 characters in your search you could use a scalar UDF as below
CREATE FUNCTION dbo.normalizeChars
(#Name NVARCHAR(100))
RETURNS NVARCHAR(100)
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS
BEGIN
SET #Name = REPLACE(#Name,'''', '')
SET #Name = REPLACE(#Name,'`', '')
SET #Name = REPLACE(#Name,'-', '')
RETURN #Name
END