How to write own Solr custom functional query to apply few selected field - spring-mvc

Base on my requirement i have to write and apply function on few query selection fields.
The below query is, i have to convert from mysql to solr. Is possible to apply custom function on Solr or any other way to achieve this in solr kindly share.
Mysql:
select t.titleNo ,
(select udConvertCurreny(t.currentPrice,T.currency, #preferredCurrency)
from offerTitle
where titleNo = T.titleNo
and applyDate = now() ) as price
from title as T;
Function:
DELIMITER $$
CREATE FUNCTION udfConvertCurrency ( currentPrice decimal, currency varchar, preferredCurrency varchar)
RETURNS INT
BEGIN
IF currency != 'rs' THEN
currentPrice = currentPrice / (select currencyRate from currency where currencytype =currency );
RETURN currentPrice;
END; //
DELIMITER ;

Related

How would I extend INTERSECT for an arbitrary number of intersections in a stored procedure?

I have a table like StockItem { StoreId, ItemId } (where both fields are foreign keys), which details all items stocked in each store.
To answer the question "which stores stock X and Y" I can use INTERSECT like:
CREATE OR REPLACE PROCEDURE FindStoresStockingBothItems (
X IN NUMBER, Y IN NUMBER
) AS
BEGIN
select StoreId from StockItem where ItemId = X
INTERSECT
select StoreId from StockItem where ItemId = Y;
END;
My use case is to call from C# in a method like List<int> FindStoresStockingBothItems(int x,int y)
But what if I want to extend this to a variable number of items? My C# method signature might now be List<int> FindStoresSellingAllItems(List<int> items) but I've no idea how to do this in PL/SQL - either how to do the multiple intersections or how to pass in a variable number of input item Ids.
What might a PL/SQL stored procedure look like?
A very simple solution, albeit not beautiful, would be to pass a string with the values:
CREATE OR REPLACE PROCEDURE FindStoresStockingBothItems (p_ids VARCHAR2) AS
v_storeid INTEGER;
BEGIN
SELECT storeid
INTO v_storeid
FROM stockitem
WHERE ',' || p_ids || ',' LIKE '%,' || ItemId || ',%'
GROUP BY storeid
HAVING COUNT(*) = REGEXP_COUNT(p_ids, ',') + 1;
END;

Error in Insert function in postgresql

CREATE OR REPLACE FUNCTION InsertInformation
(
p_Name varchar(20)
,p_Address varchar(250)
,p_Mobile int
) RETURNS VOID
as $$
begin
declare v_ID int;
BEGIN
select coalesce(max(Id),0) into v_ID from Information
set; v_ID=v_ID+1
insert into Information
(
Id
,Name
,Address
,Mobile
)
values
(
v_ID
,p_Name
,p_Address
,p_Mobile
)
select v_ID;
$$
LANGUAGE plpgsql;
I convert my sql insert sp to Postgres function using online converter tool but it showing the below mention error
error showing : ERROR: syntax error at or near "insert"
LINE 16: insert into Information
This:
select coalesce(max(Id),0) into v_ID from Information
set; v_ID=v_ID+1
Is wrong.
The select isn't properly terminated, and the set itself is illegal syntax.
You probably want this:
select coalesce(max(Id),0)
into v_ID
from Information; --<< terminate with a ; here
v_id := v_id + 1; --<< terminate with a ; here
But the extra assignment isn't necessary in the first place. The above can be shortened to:
select coalesce(max(Id),0) + 1
into v_ID
from Information;
This
select v_ID;
is also wrong. To return a value use:
return v_id;
But your function is defined as returns void so you can't return anything in the first place.
But: using select coalesce(max(Id),0) + 1 to generate unique IDs is wrong and will not work correctly in a real world application.
The only correct, scalable and fast way to generate new ids is to use a sequence. Really.
The complete function (if you want to return the newly "generated" id) would look like this:
CREATE OR REPLACE FUNCTION InsertInformation(p_Name varchar(20),p_Address varchar(250),p_Mobile int)
RETURNS integer
as
$$
declare
v_ID int;
BEGIN
select coalesce(max(Id),0) + 1
into v_ID
from Information;
INSERT INTO information
(id, name, address, mobile)
VALUES
(v_id, p_name, p_address, p_mobile);
return v_id;
END;
$$
LANGUAGE plpgsql;
SQLFiddle example: http://sqlfiddle.com/#!15/4ac27/1

PL/SQL - comma separated list within IN CLAUSE

I am having trouble getting a block of pl/sql code to work. In the top of my procedure I get some data from my oracle apex application on what checkboxes are checked. Because the report that contains the checkboxes is generated dynamically I have to loop through the
APEX_APPLICATION.G_F01
list and generate a comma separated string which looks like this
v_list VARCHAR2(255) := (1,3,5,9,10);
I want to then query on that list later and place the v_list on an IN clause like so
SELECT * FROM users
WHERE user_id IN (v_list);
This of course throws an error. My question is what can I convert the v_list to in order to be able to insert it into a IN clause in a query within a pl/sql procedure?
If users is small and user_id doesn't contain commas, you could use:
SELECT * FROM users WHERE ',' || v_list || ',' LIKE '%,'||user_id||',%'
This query is not optimal though because it can't use indexes on user_id.
I advise you to use a pipelined function that returns a table of NUMBER that you can query directly. For example:
CREATE TYPE tab_number IS TABLE OF NUMBER;
/
CREATE OR REPLACE FUNCTION string_to_table_num(p VARCHAR2)
RETURN tab_number
PIPELINED IS
BEGIN
FOR cc IN (SELECT rtrim(regexp_substr(str, '[^,]*,', 1, level), ',') res
FROM (SELECT p || ',' str FROM dual)
CONNECT BY level <= length(str)
- length(replace(str, ',', ''))) LOOP
PIPE ROW(cc.res);
END LOOP;
END;
/
You would then be able to build queries such as:
SELECT *
FROM users
WHERE user_id IN (SELECT *
FROM TABLE(string_to_table_num('1,2,3,4,5'));
You can use XMLTABLE as follows
SELECT * FROM users
WHERE user_id IN (SELECT to_number(column_value) FROM XMLTABLE(v_list));
I have tried to find a solution for that too but never succeeded. You can build the query as a string and then run EXECUTE IMMEDIATE, see http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/dynamic.htm#i14500.
That said, it just occurred to me that the argument of an IN clause can be a sub-select:
SELECT * FROM users
WHERE user_id IN (SELECT something FROM somewhere)
so, is it possible to expose the checkbox values as a stored function? Then you might be able to do something like
SELECT * FROM users
WHERE user_id IN (SELECT my_package.checkbox_func FROM dual)
Personally, i like this approach:
with t as (select 'a,b,c,d,e' str from dual)
--
select val
from t, xmltable('/root/e/text()'
passing xmltype('<root><e>' || replace(t.str,',','</e><e>')|| '</e></root>')
columns val varchar2(10) path '/'
)
Which can be found among other examples in Thread: Split Comma Delimited String Oracle
If you feel like swamping in even more options, visit the OTN plsql forums.

How to use Split function in stored procedure?

I am selecting the values like below:
select browser, firstname, lastname from details
Here the browser value will be like this:
33243#Firefox#dsfsd
34234#google#dfsd
And separately I have used split function for single value as below:
select * from dbo.split('33243#Firefox#dsfsd','#')
Result is:
items
===========
33243
firefox
dsfsd
So I have used split function like below
select split(browser, '#'), firstname, lastname from details
but its not working...
What I need is
33243#Firefox#dsfsd
instead of displaying the value like this into the grid,
have to display only Firefox into the grid.
Since you know you want the second element each time, you could write a function like this:
CREATE FUNCTION [dbo].[fn_SplitElement]
(
#inputString nvarchar(2000), --The input string
#elem int, --The 1-based element index to return,
#delimiter nvarchar(1) --The delimiter char
)
RETURNS nvarchar(2000)
AS
BEGIN
-- Declare the return variable here
DECLARE #result nvarchar(2000)
-- Add the T-SQL statements to compute the return value here
SELECT #result = value
FROM
(
SELECT *,ROW_NUMBER() OVER(ORDER By Position) as rownum FROM dbo.split(#inputString,#delimiter)
) as t
WHERE rownum=#elem
-- Return the result of the function
RETURN #result
END
GO
Then you can call:
select [dbo].[fn_SplitElement](browser,2,'#') as 'BrowserName', firstname, lastname from details
You do not state which version of SQL Server you are using or which split function. However, most split functions return a table rather than rows so you'll need to use a JOIN to join the two tables (the first is the split, the second is the rest of the fields).
For more information in SQL split functions, see Erland Sommarskog's page at http://www.sommarskog.se/arrays-in-sql.html .
You can Create a Split function and that will be use when you want.
CREATE FUNCTION [dbo].[Split]
(
#List nvarchar(max),
#SplitOn nvarchar(1)
)
RETURNS #RtnValue table (
Id int identity(1,1),
Value nvarchar(max)
)
AS
BEGIN
While (Charindex(#SplitOn,#List)>0)
Begin
Insert Into #RtnValue (value)
Select
Value = ltrim(rtrim(Substring(#List,1,Charindex(#SplitOn,#List)-1)))
Set #List = Substring(#List,Charindex(#SplitOn,#List)+len(#SplitOn),len(#List))
End
Insert Into #RtnValue (Value)
Select Value = ltrim(rtrim(#List))
Return
END
after that you can call the function in your query as below.
SELECT * FROM anotherTable WHERE user_id IN(dbo.split(#user_list,','))
I Have used below query instead of using split function.. its working perfectly..
select
SUBSTRING(SUBSTRING(browser, CHARINDEX ('#', browser)+1,LEN(browser)-charindex('#', browser)),
0,
CHARINDEX('#',SUBSTRING(browser, CHARINDEX ('#', browser)+1,LEN(browser)-CHARINDEX('#', browser)))),
firstname, lastname from details

SQL use comma-separated values with IN clause

I am developing an ASP.NET application and passing a string value like "1,2,3,4" into a procedure to select those values which are IN (1,2,3,4) but its saying "Conversion failed when converting the varchar value '1,2,3,4' to data type int."
Here is the aspx code:
private void fillRoles()
{
/*Read in User Profile Data from database */
Database db = DatabaseFactory.CreateDatabase();
DbCommand cmd = db.GetStoredProcCommand("sp_getUserRoles");
db.AddInParameter(cmd, "#pGroupIDs", System.Data.DbType.String);
db.SetParameterValue(cmd, "#pGroupIDs", "1,2,3,4");
IDataReader reader = db.ExecuteReader(cmd);
DropDownListRole.DataTextField = "Group";
DropDownListRole.DataValueField = "ID";
while (reader.Read())
{
DropDownListRole.Items.Add((new ListItem(reader[1].ToString(), reader[0].ToString())));
}
reader.Close();
}
Here is my procedure:
CREATE Procedure [dbo].[sp_getUserRoles](#pGroupIDs varchar(50))
AS BEGIN
SELECT * FROM CheckList_Groups Where id in (#pGroupIDs)
END
Here is a workaround I found to do what you are trying to achieve
CREATE Procedure [dbo].[sp_getUserRoles](
#pGroupIDs varchar(50)
)
As
BEGIN
SELECT * FROM CheckList_Groups Where (',' + #pGroupIDs +',' LIKE '%,' + CONVERT(VARCHAR, id) + ',%')
End
This gets your comma delimited list and compares it to the id's(which are represented like so ',1,', ',2,' etc) in the table using LIKE
If you dont want to use dynamic sql, the best way ive found is to create a function which turns a delimited string into a table, something like this works for an Integer list:
CREATE FUNCTION [dbo].[StringToIntList]
(#str VARCHAR (MAX), #delimeter CHAR (1))
RETURNS
#result TABLE (
[ID] INT NULL)
AS
BEGIN
DECLARE #x XML
SET #x = '<t>' + REPLACE(#str, #delimeter, '</t><t>') + '</t>'
INSERT INTO #result
SELECT DISTINCT x.i.value('.', 'int') AS token
FROM #x.nodes('//t') x(i)
ORDER BY 1
RETURN
END
Then use that in your sp:
CREATE Procedure [dbo].[sp_getUserRoles](
#pGroupIDs varchar(50)
)
As
BEGIN
SELECT * FROM CheckList_Groups Where id in (
SELECT ID FROM dbo.StringToIntList(#pGroupIds,',')
)
End
Sure it can't do that,
The generated query would be sth like this
SELECT * FROM CheckList_Groups Where id in ('1,2,3,4')
and sure it can't be executed.
you can build the query in your stored procedure then execute it with exec
'SELECT * FROM CheckList_Groups Where id in (' + #pGroupIDs + ')'
or
SELECT * FROM CheckList_Groups Where charindex(','+id+',' , #pGroupIDs)>0
but you first must add the ',' to start and end of your parameter in your c# code
It is not possible to put those values (the comma separated string) in a parameter-value.
What you'll have to do, is to create the SQL Statement in your stored procedure dynamically, by string concatenation. You'll have to execute it with the sp_executesql stored procedure then.
CREATE PROCEDURE [dbo].[getUserRoles]( #groupIds NVARCHAR(50) )
AS BEGIN
DECLARE #statement NVARCHAR(255)
SELECT #statement = N'SELECT * FROM CheckList_Groups Where id in ( ' + #pGroupIDs + N')'
execute sp_executesql #statement
END
Also, not that I named the SP getUserRoles instead of sp_getUserRoles.
The reason is very simple: when you execute a stored procedure whose name starts with sp_, then SQL Server will first query the master database to find that stored procedure, which causes a performance hit offcourse.
The way you are trying to do this is slightly wrong. You will need to use EXECUTE in order to achieve this.
CREATE PROCEDURE [dbo].[sp_getUserRoles](#pGroupIDs nvarchar(50))
As
BEGIN
EXECUTE (N'SELECT * FROM CheckList_Groups Where id in (' + #pGroupIDs + ')';
END
DECLARE #TagId NVARCHAR(100) = '43,81'
SELECT * FROM TABLE WHERE TagId IN (SELECT TRIM(VALUE) FROM STRING_SPLIT( #TagId , ',' ) )
USE STRING_SPLIT FUNCTION FOR THIS
You need to use SP_executesql to achieve this functionllity
CREATE Procedure [dbo].[sp_getUserRoles](
#pGroupIDs varchar(50)
)
As
BEGIN
EXECUTE sp_executesql
N'SELECT * FROM CheckList_Groups Where id in (#pGroupIDs)',
N'#level varchar(50)',
#level = #pGroupIDs;
End
The IN clause can't take a bound parameter like that. What it's being given when the query is actually created is SELECT * FROM CheckList_Groups Where id in ('1,2,3,4'). Essentially the IN clause is being passed a single string.
First create function -
Just run this code
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[CSVToTable] (#InStr VARCHAR(MAX))
RETURNS #TempTab TABLE
(id int not null)
AS
BEGIN
;-- Ensure input ends with comma
SET #InStr = REPLACE(#InStr + ',', ',,', ',')
DECLARE #SP INT
DECLARE #VALUE VARCHAR(1000)
WHILE PATINDEX('%,%', #INSTR ) <> 0
BEGIN
SELECT #SP = PATINDEX('%,%',#INSTR)
SELECT #VALUE = LEFT(#INSTR , #SP - 1)
SELECT #INSTR = STUFF(#INSTR, 1, #SP, '')
INSERT INTO #TempTab(id) VALUES (#VALUE)
END
RETURN
END
GO
Then -
Use function in bracket with select statment -
DECLARE #LIST VARCHAR(200)
SET #LIST = '1,3'
SELECT Id, Descr FROM CSVDemo WHERE Id IN (SELECT * FROM dbo.CSVToTable(#LIST))

Resources