CREATE OR REPLACE FUNCTION page(IN i_app name character varying, IN i_photo_id big int, IN i_page integer, IN i_member_id big int, OUT o_similar_page_name character varying, OUT o_similar_page_id big int, OUT o_similar_photo_id big int[])
DECLARE
v_limit INTEGER := 4;
v_offset INTEGER;
BEGIN
SET SEARCH_PATH = '';
v_start_time = DAYTIME();
i_app name = UPPER(i_app name);
IF i_app name <> 'DD' THEN
RAISE EXCEPTION 'Enter Valid Application Name';
END IF;
IF i_page = 1 THEN
v_offset := 0;
ELSE
v_offset := i_page * v_limit - v_limit;
END IF;
Please help me.
Answer
No.
Reason
Its not actually the purpose of SOLR. Functions has to be written in the DB level and the data that is retrieved out of query will be stored in SOLR for fast retrieval.
ALTERNATIVE SOLUTION
You can create the function and call it in the select statement to index the data into SOLR.
Note : Final results fetched out of functions can be stored in the SOLR.
Example:
CREATE FUNCTION CustomerLevel(p_creditLimit double) RETURNS VARCHAR(10)
DETERMINISTIC
BEGIN
DECLARE lvl varchar(10);
IF p_creditLimit > 50000 THEN
SET lvl = 'PLATINUM';
ELSEIF (p_creditLimit <= 50000 AND p_creditLimit >= 10000) THEN
SET lvl = 'GOLD';
ELSEIF p_creditLimit < 10000 THEN
SET lvl = 'SILVER';
END IF;
RETURN (lvl);
END
Query to used in SOLR for Indexing
SELECT CustomerLevel(123123123) as CustomerLevel from CustomerRating;
Related
I have an Oracle function that needs to be converted to SQL-Server function
This is the Oracle Function:
FUNCTION check_education(in_crs_code IN VARCHAR2)
RETURN BOOLEAN IS
v_bool BOOLEAN := FALSE;
v_dummy VARCHAR2(1);
CURSOR find_education IS
SELECT 'x'
FROM KU_LIBRARY_EDUCATION_EXTLOAN
WHERE UPPER(course_code) = UPPER(in_crs_code) AND in_use = 'Y';
BEGIN
OPEN find_education;
FETCH find_education INTO v_dummy;
IF find_education%FOUND THEN
v_bool := TRUE;
ELSE
v_bool := FALSE;
END IF;
CLOSE find_education;
RETURN (v_bool);
END check_education;
This is what I have written in SQL-Server to replicate Oracle function:
CREATE FUNCTION [dbo].[check_education](#in_crs_code VARCHAR(4000))
RETURNS BIT AS
BEGIN
DECLARE #v_bool BIT = 0;
DECLARE #v_dummy VARCHAR(1);
DECLARE find_education CURSOR LOCAL FOR
SELECT 'x'
FROM [dbo].[KU_LIBRARY_EDUCATION_EXTLOAN]
WHERE UPPER(course_code) = UPPER(#in_crs_code)
AND in_use = 'Y';
OPEN find_education;
FETCH find_education INTO #v_dummy;
IF ##CURSOR_ROWS >1 BEGIN
SET #v_bool = 1;
END
ELSE BEGIN
SET #v_bool = 0;
END
CLOSE find_education;
DEALLOCATE find_education;
RETURN (#v_bool);
END;
I would expect the SQL server function to return 1 if the cursor returns 'x' but i'm getting 0. Anu help will be appreciated.
I would suggest using an inline table valued function instead of a scalar function. To make sure this is an inline table valued function it MUST be a single select statement. This means there can't be loops and other stuff. Fortunately this query does not actually need any loops. A simple count will return the number of rows. And any value other than 0 when converted to a bit will always be 1.
CREATE FUNCTION [dbo].[check_education]
(
#in_crs_code VARCHAR(4000)
) RETURNS table as return
SELECT CourseExists = convert(bit, count(*))
FROM [dbo].[KU_LIBRARY_EDUCATION_EXTLOAN]
WHERE UPPER(course_code) = UPPER(#in_crs_code)
AND in_use = 'Y';
This is a mere EXISTS thing, so we could try
CREATE FUNCTION [dbo].[check_education](#in_crs_code VARCHAR(4000)) RETURNS BIT AS
BEGIN
RETURN EXISTS ( <query> )
END;
But as far as I know, SQL Server doesn't accept this (though I cannot say why not - maybe it's because of their lack of a real boolean; Oracle doesn't accept it, because EXISTS is no keyword in their PL/SQL programming language).
So we'd use IF/ THEN/ ELSE:
CREATE FUNCTION [dbo].[check_education](#in_crs_code VARCHAR(4000)) RETURNS BIT AS
BEGIN
IF EXISTS
(
SELECT 'x'
FROM ku_library_education_extloan
WHERE UPPER(course_code) = UPPER(in_crs_code) AND in_use = 'Y'
)
RETURN 1
ELSE
RETURN 0
END
END;
There may be errors, because I've never coded a stored procedure in T-SQL, but anyway, you get the idea.
I need to store a string value in a field in a table, specifically in its Subcategory VarChar(50) column.
The value of Subcategory prior to this post processing is either 0 or 1; I need to change that to a more human-friendly value.
I haven't created a database trigger in decades and need some help with the code. This is my pseudo SQL (a hodgepodge of SQL and VB):
CREATE OR REPLACE TRIGGER tr_CustomerCategoryLog_BeforeInsert
BEFORE INSERT ON CustomerCategoryLog FOR EACH ROW
DECLARE _Category = :new.Category;
DECLARE _Subcategory = :new.Subcategory;
BEGIN
If _Category = "New"
If _Subcategory = 0
:new.Subcategory := 'New';
End If
Else If _Subcategory = 1
:new.Subcategory := 'Assumed';
End If
End If
If _Category = "Existing"
If _Subcategory = 0
:new.Subcategory := 'Existing';
End If
Else If _Subcategory = 1
:new.Subcategory := 'Organic'
End If
End If
Return "Unknown"
End Function
END;
If the logic isn't clear, in semi-plain English it is:
If the value of the Category field is "New", set the Subcategory field value also to "New" if the value of Subcategory is currently 0; otherwise, set it to "Assumed"
If the value of the Category field is "Existing", set the Subcategory field value also to "Existing" if the value of Subcategory is currently 0; otherwise, set it to "Organic"
Maybe I need to give Steely Dan's album "Trigger Logic" a listen.
UPDATE
I think the answer will work, but it's not complete enough for me.
Since I apparently have Oracle code mixed up in the pseudoSQL above, what would the complete code need to look like (to create a BeforeInsert trigger on the CustomerCategoryLog table)?
Is this more like it:
CREATE TRIGGER tr_CustomerCategoryLog_BeforeInsert
ON CustomerCategoryLog
INSTEAD OF INSERT
AS
BEGIN
SELECT
CASE
WHEN #Category = 'New'
THEN CHOOSE(#Subcategory + 1, 'New', 'Assumed')
WHEN #Category = 'Existing'
THEN CHOOSE(#Subcategory + 1, 'Existing', 'Organic')
ELSE 'Unknown'
END
END
?
I tend to avoid triggers (perhaps a character flaw... I also don't like mashed potatoes), but the following illustration could simplify your logic
Declare #Category varchar(50) = 'Existing'
Declare #Subcategory int = 1 -- works if BIT
Select case when #Category = 'New' then choose(#Subcategory+1,'New','Assumed')
when #Category = 'Existing' then choose(#Subcategory+1,'Existing','Organic')
else 'Unknown' end
Returns
Organic
I have a problem that i've spent about 3 days on.
I have a table(CDKEY) with 6 columns: CDKEYSEQ, Userseq,Banned, Communityseq, cdkey, Email.
Banned is always 0 (at this point), Userseq is NULL unless someone logged on/registered with the cdkey and email is NULL until the cdkey is registered.
Basically Userseq doesn't get filled in until a user logs in. So there will always be an email value before a user sequence value.
NOW The issue:
I'm trying to create a stored procedure that gets called when someone wants a cdkey (which they provide an email for).
The procedure first checks a table called community to make sure the Community exists.
Then if the Community exists The procedure is supposed to check the CDKEY Table for a key that has the correct community sequence AND AlSO has a NULL Value for both USERSEQ and EMAIL.
Obviously using just a select query doesnt work because there are multiple rows that are returned that match those conditions.
I tried using cursors, which got me a little further.
The problem with the cursors is that when I had two conditions after the WHERE clause, it didnt return anything.
Here is my current Procedure Code:
create or replace PROCEDURE KEYREGISTRATION(
PRODUCT_IN IN VARCHAR2 ,
in_CPUID IN LONG ,
in_MACID IN LONG ,
in_MACID2 IN LONG ,
in_HDID IN LONG ,
in_PCCores IN LONG ,
in_PCName IN VARCHAR2 ,
in_Email IN VARCHAR2 ,
out_cdkey OUT VARCHAR2 ,
returncode OUT NUMBER )
AS
CodeSuccess CONSTANT NUMBER := 0;
CoreError CONSTANT NUMBER := 2;
CodeAlreadyExists CONSTANT NUMBER := 3;
CodeBadProduct CONSTANT NUMBER := 4;
new_cdkey VARCHAR2(50);
old_cdkey VARCHAR2(50);
acommunitySeq NUMBER;
BEGIN
acommunitySeq := 0;
new_cdkey := '';
old_cdkey := '';
SELECT COMMUNITYSEQ INTO acommunityseq FROM COMMUNITY WHERE NAME = PRODUCT_IN;
returncode := CodeSuccess;
/*EXCEPTION
WHEN NO_DATA_FOUND THEN
returncode := CodeBadProduct; */
IF returncode = CodeSuccess THEN
BEGIN
SELECT CDKEY INTO old_cdkey FROM CDKEY WHERE EMAIL = in_email;
returncode := CodeBadProduct;
out_cdkey := old_cdkey;
RETURN;
EXCEPTION
WHEN NO_DATA_FOUND THEN
returncode := CodeSuccess;
END;
END IF;
IF returncode = CodeSuccess THEN
/*SELECT CDKEY into new_cdkey FROM CDKEY WHERE EMAIL = NULL AND COMMUNITYSEQ = acommunityseq; */
DECLARE
CURSOR c1
IS
SELECT CDKEY FROM CDKEY WHERE COMMUNITYSEQ = acommunityseq AND EMAIL = NULL;
BEGIN
OPEN c1;
FETCH c1 INTO new_cdkey;
IF ( c1%notfound ) THEN
returncode := CoreError;
END IF;
UPDATE cdkey SET EMAIL = in_email WHERE CDKEY = new_cdkey;
INSERT INTO user_hw VALUES( EMAIL = in_email, CPUID = in_cpuid,
MACID = in_macid, MACID2 = in_macid2, CPUCORES = in_pccores, PCNAME = in_pcname;
out_cdkey := new_cdkey;
returncode := CodeSuccess;
COMMIT;
END;
ELSE
returncode := CoreError;
ROLLBACK;
END IF;
END KEYREGISTRATION;
You think a query will not work - and your reasoning is "because a query will return too many rows." That is incorrect. Add a WHERE clause (or add to the filters you already have), with the condition ROWNUM = 1 - this will return the first row that meets all the other conditions, the processing will end, and you will get just this row and nothing else.
I came across the following solution but it does not work on Sybase
SELECT CONVERT(varchar, CAST(987654321 AS money), 1)
I have read the Convert Sybase information but still i receive the same number without the commas.
Have you tried giving a varchar (20) for example instead ? something like :
SELECT CONVERT(varchar(20), CAST(987654321 AS money), 1)
In SqlAnywhere money datatype is a domain, implemented as NUMERIC(19,4).
in CAST function , If you do not indicate a length for character string types, the database server chooses an appropriate length. If neither precision nor scale is specified for a DECIMAL conversion, the database server selects appropriate values.
So maybe this is what's causing the issue, what do you get as output ? do you get 987654321.00 , or just 987654321 ?
Update:
My last suggestion would be using insertstr() function and loop through the char value of your number to insert comma every 3 digits .. this is not the cleanest/easiest way but apparently SQLAnywhere deal with money datatype as normal NUMERIC datatype ...
insertstr() documentation is here.
I would give you a code sample but I don't have SQLAnywhere installed to test it ...
Here is the SP i created based on F Karam suggestion.
CREATE FUNCTION "DBA"."formattednumber"( in #number numeric)
returns char(60)
begin
declare #returnnumber char(60);
declare #workingnumber char(60);
declare #n_ind char(1);
declare #decimalnumber char(10);
declare #tempnumber char(60);
declare #decimalpos integer;
if isnull(#number,'') = '' then
return null
end if;
if #number < 0 then set #n_ind = 'Y'
else set #n_ind = 'N'
end if;
set #workingnumber = convert(char(60),ABS(#number));
set #decimalpos = patindex('%.%',#workingnumber);
if #decimalpos > 0 then
set #decimalnumber = substr(#workingnumber,#decimalpos);
set #decimalnumber = "left"(#decimalnumber,3+1);
set #workingnumber = "left"(#workingnumber,#decimalpos-1)
end if end if;
set #returnnumber = '';
while length(#workingnumber) > 3 loop
set #tempnumber = "right"(#workingnumber,3);
set #returnnumber = insertstr(0,#returnnumber,#tempnumber);
set #workingnumber = "left"(#workingnumber,length(#workingnumber)-3);
if length(#workingnumber) > 0 then
set #returnnumber = insertstr(0,#returnnumber,',')
end if
end loop;
if length(#workingnumber) > 0 then
set #returnnumber = insertstr(0,#returnnumber,#workingnumber)
end if;
if length(#decimalnumber) > 0 then
set #returnnumber = #returnnumber+#decimalnumber
end if;
if #n_ind = 'Y' then set #returnnumber = '-' || #returnnumber
end if;
return(#returnnumber)
end;
You need to distinguish between server-side and client-side formatting. When you use the 'isql' client for example (the TDS client), then the result will be this:
1> select convert(money, 9876543210)
2> go
9876543210
------------------------
9,876,543,210.00
(1 row affected)
But this is purely because the client application happens to format 'money' values this way. Also, this is actually not specific for SQLA, since isql is originally the client tool for ASE (a different Sybase database).
When you run the same conversion at the SQLA server (i.e. as part of an expression in a SQL statement), those commas will not be there since SQLA doesn't have such a built-in formatting style.
If you want this, you should write a SQL function that formats the number as you desire.
I have a java front end that has a table of data. We need to save this data to the Database via stored procedure. If the passed parameter is a just an array, I am able to access the contents easily. But if the contents of the array is a also a row type, thats the part im having trouble with.
I dont know how to access the contents of the array.
Im using DB2 10.1
CREATE TABLE "TEST"."CHART_ACCT" (
"ACCT_NO" VARCHAR(10) NOT NULL,
"ACCT_DESC" VARCHAR(40) NOT NULL
)
ORGANIZE BY ROW
DATA CAPTURE NONE
IN "USERSPACE1"
COMPRESS YES ADAPTIVE
VALUE COMPRESSION#
CREATE OR REPLACE TYPE TEST.ACCT AS ROW ANCHOR ROW OF TEST.CHART_ACCT#
CREATE OR REPLACE TYPE TEST.ACCT_ARR AS TEST.ACCT ARRAY[]#
CREATE OR REPLACE PROCEDURE TEST.TEST_ARRAY (IN P_ACCT_ARR TEST.ACCT_ARR)
P1: BEGIN
-- #######################################################################
-- #
-- #######################################################################
DECLARE i INTEGER;
SET i = 1;
WHILE i < 10 DO
CALL DBMS_OUTPUT.PUT_LINE(P_GLACCT_ARR[i]);
set i = i + 1;
END WHILE;
END P1#
You need to declare a temporary variable of the row type and assign array elements to it in a loop:
CREATE OR REPLACE PROCEDURE TEST_ARRAY (IN P_ACCT_ARR ACCT_ARR)
P1: BEGIN
DECLARE i INTEGER;
DECLARE v_acct acct;
SET i = 1;
WHILE i < CARDINALITY(p_acct_arr) DO
SET v_acct = p_acct_arr[i];
CALL DBMS_OUTPUT.PUT_LINE('Account number = ' || v_acct.acct_no);
set i = i + 1;
END WHILE;
END P1#
However, a more concise way to do that is to use the collection-derived table reference:
CREATE OR REPLACE PROCEDURE TEST_ARRAY (IN P_ACCT_ARR ACCT_ARR)
P1: BEGIN
FOR r AS (SELECT * FROM UNNEST(p_acct_arr) t ) DO
CALL DBMS_OUTPUT.PUT_LINE('Account number = ' || r.acct_no);
END FOR;
END P1#