i am writing stored procedures in MySQL that return values;
CREATE PROCEDURE getCustomerById (id int)
BEGIN
SELECT *
FROM customer
WHERE customer.id = id;
END;
and i get the error that the results cannot be shown in the given context.
after some googling, i think that i need to set the flag "CLIENT_MULTI_RESULTS" - i am connecting the database from JDBC using a java app, but cant find where to set it!
any suggestions?
try this
delimiter ;
drop procedure if exists getCustomerById;
delimiter #
create procedure getCustomerById
(
in p_id int unsigned
)
begin
select c.* from customer c where c.id = p_id;
end #
delimiter ;
Related
How can I return a set of data from PL/SQL?
I have a stored procedure that needs to run a select statement and returns the result back to the calling (Java) program.
The select statement comprises of a few joins from multiple tables, so I am not sure how to define this type in the stored procedure definition or body.
I was thinking maybe this can be done as following, but SQL Developer is giving me errors:
CREATE OR REPLACE PACKAGE my_package
AS
TYPE a_collection_records IS RECORD (
NUMBER FIRST_COL,
VARCHAR2 SECOND_COL -- a few others
);
-- Procedure API that uses a_collection_records type
END;
CREATE OR REPLACE PROCEDURE sample_procedure(
p_some_select_sql_result OUT my_package.a_collection_records
)
AS
BEGIN
-- Populate p_some_select_sql_result with some select data
END;
Unless you are particularly set on using a collection, it would be simpler to use a ref cursor:
CREATE OR REPLACE PROCEDURE sample_procedure (
p_some_select_sql_result OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN p_some_select_sql_result FOR
SELECT ...
FROM ...
JOIN ...
... etc.;
END;
/
From JDBC you can then do something like:
cStmt = conn.prepareCall('{ call sample_procedure(?) }');
cStmt.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
cStmt.execute();
rSet = cStmt.getCursor(1);
and you can then iterate over the result set as you would with any other.
You could also use a function instead:
CREATE OR REPLACE FUNCTION sample_function RETURN SYS_REFCURSOR
AS
l_some_select_sql_result
BEGIN
OPEN l_some_select_sql_result FOR
SELECT ...
FROM ...
JOIN ...
... etc.;
RETURN l_some_select_sql_result;
END;
/
and
cStmt = conn.prepareCall('{ ?=call sample_function }');
cStmt.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
cStmt.execute();
rSet = cStmt.getCursor(1);
Obviously you need to handle any other parameters you're passing to your real procedure/function.
Your type definition is a little bit out of order. You have the type definition before the name of the item.
TYPE a_collection_records IS RECORD (
NUMBER FIRST_COL,
VARCHAR2 SECOND_COL -- a few others
);
It should be
TYPE a_collection_records IS RECORD (
FIRST_COL NUMBER,
SECOND_COL VARCHAR2 -- a few others
);
The name of the column comes before the column's datatype. I hope this is what you are looking for. You could always do a refcursor, but if you want names that are not the actual column names on the tables you are selecting from then you will still what a record type.
To be able to create it as a custom set just declare after the close of the RECORD definition the following line of code
TYPE collection_list IS TABLE a_collection_records;
Complete example:
TYPE a_collection_records IS RECORD (
FIRST_COL NUMBER,
SECOND_COL VARCHAR2 -- a few others
);
TYPE collection_list IS TABLE OF a_collection_records;
That will give you a custom (and column masked) set of data.
(Edit 1: not Date but wc_Event.date)
I created a query (with subquery) that executes perfectly but I have trouble converting it either to a JPA query or a stored procedure.
This is my query:
SELECT * FROM wc_Event WHERE (wc_Event.date > CURRENT_DATE())
AND wc_Event.evt_id IN
(
SELECT event_users.evt_id FROM event_users
WHERE event_users.usr_id = 1
)
ORDER BY wc_Event.date
I have tried this for stored procedure:
CREATE PROCEDURE getFutureRegistredEvents
(
my_user_id int
)
BEGIN
SELECT * FROM wc_Event WHERE (wc_Event.date > CURRENT_DATE())
AND wc_Event.evt_id IN
(
SELECT event_users.evt_id FROM event_users
WHERE event_users.usr_id = my_user_id
)
ORDER BY wc_Event.date
END
It tells me to use the right syntax at line 13 (= END) but even if I add a semicolon to it my query wont work.
I also tried creating the same effect with JPA queries but with no effect.
What am I doing wrong?
Thanks in advance
Bert
I am new to MySQL and I wrote a simple query bellow:
CREATE Table tblFeedBack
(
`FeedBackID` INT AUTO_IncremeNT,
`UserID` INT,
`Inserted_TS` TIMESTAMP ,
`FeedBackValue` VARCHAR(100),
PRIMARY KEY (FeedBackID)
);
CREATE PROCEDURE tblFeedBack_InsertUpdate
(
IN U_ID INT,
IN FB_Value VARCHAR(50)
)
BEGIN
IF ((Select COUNT(*) From 'tblFeedback') < 3)
BEGIN
INSERT INTO 'tblFeedBack' (`UserID`,`FeedBackValue`)
VALUES (U_ID,FB_Value);
END
ELSE
BEGIN
DECLARE #MostRecentFID INT;
SELECT TOP 1 `FeedBackID` FROM tblFeedback
WHERE UID = U_ID
ORDER BY `Inserted_TS` DESC
INTO #MostRecentFID;
UPDATE tblfeedback
SET `FeedBackValue` = #FeedBackValue
WHERE `FeedBackID` = #MostRecentFID
END
END
I am getting this error:
Schema Creation Failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''tblFeedBack' (`UserID`,`FeedBackValue`) VALUES (1,'12')' at line 9
Can anyone please help me solve this one?
Thanks in advance.
MySQL does not supportĀ TOP you want to use LIMIT 1 instead as they are ordered.
Select `FeedBackID` FROM tblFeedback
WHERE UID = U_ID
ORDER BY `Inserted_TS` DESC
LIMIT 1
INTO #MostRecentFID;
Also, when you query a table using quotes it becomes case sensitive.
IF ((Select COUNT(*) From 'tblFeedback') < 3)
Should be
IF ((Select COUNT(*) From 'tblFeedBack') < 3)
Fix these 2 errors and it should work.
The table names are different in the insert query. One contains 'tblFeedback' and other contains 'tblFeedBack'
Also, please try to remove single quotes near table names in the query.
I am using PreparedStatement to prepare sql queries. I want to insert a row in table if and only if it doesn't exist.
I tried this -
INSERT INTO users (userId) VALUES (?) ON DUPLICATE KEY UPDATE userId = ?
But this will unnecessarily update the userId.
How can i insert the userId here ?
INSERT INTO users
(userId)
SELECT ?
WHERE NOT EXISTS
(
SELECT *
FROM users
where userId = ?
)
You may use
INSERT IGNORE INTO users (userId) VALUES (?)
But you should understand why do you want ignore errors.
on duplicate key does not work correctly when the table is an innodb. It creates exactly the problem you are describing. If you need the functionality of an innodb, then should you first check the existence of the row, otherwise can you convert the table to a myisam table.
edit: if you need to check the existence of the row before the decision to insert or update, then would I advice you to use a stored procedure.
DELIMITER //
CREATE PROCEDURE adjustusers(IN pId int)
BEGIN
DECLARE userid int;
select count(id) into userid from users where id = pId;
if userid = 1 then
update users set id = pId where id = pId;
else
insert into users(id) values(pId);
end if;
END //
DELIMITER ;
A stored procedure is precompiled, just as a prepared statement. Hence no SQL injection problems and some more functionality and only one call to the database.
I'm trying to pass an array as a String in MySQL Stored Procedure but it doesn't work fine.
Here's my SQL Codes:
CREATE DEFINER=`root`#`localhost` PROCEDURE `search_equipment`(IN equip VARCHAR(100), IN category VARCHAR(255))
BEGIN
SELECT *
FROM Equipment
WHERE e_description
LIKE CONCAT("%",equip,"%")
AND e_type IN (category)
END
And here's how i call the procedure:
String type = "'I.T. Equipment','Office Supply'";
CALL search_equipment('some equipment', type);
Any ideas?
Your friend here is FIND_IN_SET I expect. I first came across that method in this question : also covered in this question MYSQL - Stored Procedure Utilising Comma Separated String As Variable Input
MySQL documention for FIND_IN_SET is here http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set
So your procedure will become
CREATE DEFINER=`root`#`localhost`
PROCEDURE `search_equipment`(
IN equip VARCHAR(100),
IN category VARCHAR(255)
)
BEGIN
SELECT *
FROM Equipment
WHERE e_description LIKE CONCAT("%",equip,"%")
AND FIND_IN_SET(e_type,category)
END
This relies on the category string being a comma-delimited list, and so your calling code becomes
String type = "I.T. Equipment,Office Supply";
CALL search_equipment('some equipment', type);
(p.s. fixed a typo, in your arguments you had typed categoy)
you have to create a dynamic statment:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `search_equipment`(IN equip VARCHAR(100), IN category VARCHAR(255))
BEGIN
SET #s =
CONCAT('SELECT *
FROM Equipment
WHERE e_description
LIKE \'%',equip,'%\'
AND e_type IN (',category,')');
PREPARE stmt from #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt3;
END$$
This helps for me to do IN condition
Hope this will help you..
CREATE PROCEDURE `test`(IN Array_String VARCHAR(100))
BEGIN
SELECT * FROM Table_Name
WHERE FIND_IN_SET(field_name_to_search, Array_String);
END//;
Calling:
call test('3,2,1');