How to get near value from range in php - php

How to find nearest value from mysql database table of give value, what i want to do is:
CASE1: if i am giving input 2500 to pincode then i am retrieving record corresponding to that pincode value from database.
CASE2: if record not exits for entered pincode(2500) , i have to get nearest value of 2500 and its corresponding records too.
Stored procedure i am currently calling for CASE1 sp_findlocation('XXXXXXXX','2500',#addresss)
DELIMITER $$
USE `test`$$
DROP PROCEDURE IF EXISTS `sp_findlocation`$$
CREATE PROCEDURE `sp_findlocation`(IN mobile VARCHAR(20),IN pincode VARCHAR(20),OUT address VARCHAR(100))
BEGIN
IF(pincode IS NOT NULL AND pincode!= '') THEN
SET #c1 = '';
SET #c2 = '';
SET #c3 = '';
SET #qry='select locality,store_name,contact_number INTO #c1,#c2,#c3 from test_upload where pin=? limit 1';
PREPARE stmt FROM #qry;
SET #c = pincode;
EXECUTE stmt USING #c;
DEALLOCATE PREPARE stmt;
IF(#c1!='' || #c2!=''||#c3!='') THEN
SET address= CONCAT(#c1, '|',#c2,'|',#c3);
ELSE
SET address= "No Result";
END IF;
ELSE
SET address="Please enter valid pin code";
END IF;
END$$
DELIMITER ;
what i will do for geting records including CASE2?

Related

How to Create an auto-increment value on MySQL using a text field? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 months ago.
Improve this question
I tried to generate an auto increment value but MySQL does not implement it.
There are many things to solve the problem. Let me show you one of them by using MySQL procedures.
Steps are as follows:
1°) create a procedure that generates an identifier for a table (generate_id)
2°) create a procedure that inserts the data into the table (insert_users) by using the first procedure (generate_id) to get a formatted ID, then it will return the inserted ID as a SELECT query.
3°) Now, call the inserting procedure (insert_users)
For more information, chat with Michel Magloire Ekanga who is the main creator of this craftiness.
LET'S USE AN EXAMPLE FOR EACH STEP
STEP 1
generate_id procedure that should take as parameters: table_name, the primary_key, a joiner or a prefix for ID, the length for ID, and the output
Our result should be as below: USER20210909000002 (joiner=USER, year=2021, mounth=09, day=09, increment=000002)
# --------------------- DEFINITION ------------------------------
DROP PROCEDURE IF EXISTS generate_id;
DELIMITER $$
CREATE PROCEDURE generate_id(IN _db_table VARCHAR(255), IN _pkey VARCHAR(255),IN _joiner VARCHAR(255),_length INT, OUT _new_id VARCHAR(255))
BEGIN
SET #max_id = NULL;
SET #sql = CONCAT('select max(`', _pkey, '`) into #max_id from `', _db_table, '`');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
#------- Length for identifier -------
SET #length = 10;
SET #joiner_len = CHAR_LENGTH(_joiner);
IF _length > 0 AND (_length - CHAR_LENGTH(_joiner)) >= 10 THEN
SET #length = _length;
END IF;
#----------------------------
#--- the date variables ---
SET #today = DATE_FORMAT(NOW(),'%Y%m%d');
SET #r_str = LPAD(1,(#length - (8 + #joiner_len)), '0');
#
#---- FORMATING ID ------------------------
#
IF #max_id IS NULL THEN
# the table is empty
SET _new_id = CONCAT(_joiner,#today,#r_str);
ELSE
# the table is not empty
# 1°) reading parts from previous ID
SET #strlen = CHAR_LENGTH(#max_id);
SET #old_r_str = SUBSTR(#max_id, (#joiner_len + 4 + 2 + 2 + 1), #strlen);
SET #old_idx = CONVERT(#old_r_str, SIGNED INTEGER);
# 2°) checking if dates are the same
SET #old_date = SUBSTR(#max_id, (#joiner_len + 1), 8);
-- dates are not the same, we just take the 8 characters for date from the field
SET #new_idx = 1;
SET #new_r_str = LPAD(#new_idx,(#length - (8 + #joiner_len)), '0');
SET #new_max = CONCAT(_joiner,#today,#new_r_str);
IF #today = #old_date THEN
SET #new_idx = #old_idx + 1;
SET #new_r_str = LPAD(#new_idx,(#length - (8 + #joiner_len)), '0');
SET #new_max = CONCAT(_joiner,#old_date,#new_r_str);
END IF;
SET _new_id = #new_max;
END IF;
END;
$$
DELIMITER ;
STEP 2
Procedure that uses the generated ID for insertion, we don't need to provide an ID, it will generate the ID automaticaly
DROP PROCEDURE IF EXISTS insert_users;
DELIMITER $$
CREATE PROCEDURE insert_users(
login_user VARCHAR(255),
pass_user VARCHAR(255)
)
BEGIN
CALL generate_id('users', 'row_id', 'USR', 22, #new_id);
SET #last_inserted_id = #new_id;
SET #sql = CONCAT("INSERT INTO users(row_id, login_user, pass_user) VALUES ('",
#last_inserted_id, "','",
login_user, "','",
pass_user, "')"
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# ---- export the new ID before exiting the function
SELECT #last_inserted_id AS lastInsertId;
END;
$$
DELIMITER ;
STEP 3
How to use with PHP, for example
<?php
function insert(){
$db = $pdo; // I am using PDO as driver, renewed as Class
$lastInsert = null;
//---------------
$sql = "CALL insert_users(?,?)";
//---------------
$req = $db->prepare($sql);
$req->execute($login_user,$pass_user);
if($req->rowCount() > 0){
$lastInsert = $req->fetch()->lastInsertId;
return true;
}else{
return false;
}
}
?>

How to call an oracle stored procedure having in and out parameter using codeigniter?

I already setup the codeigniter dbdriver to "oci8".
For reference, here's my stored procedure. This is just my sample stored procedure.
CREATE OR REPLACE STORED PROCEDURE sp_sample(
in_id IN VARCHAR2,
out_code OUT varchar,
out_desc OUT varchar) IS
var_result VARCHAR2(100);
CURSOR GetStatus (my_id IN NUMBER) IS
SELECT status
FROM tbl_sample
WHERE id= my_id;
BEGIN
OPEN GetStatus(in_id);
LOOP
FETCH GetStatus into var_result;
EXIT WHEN GetStatus%NOTFOUND;
END LOOP;
CLOSE GetStatus;
IF(result != 'A')
UPDATE tbl_sample SET status = 'A'
WHERE id = in_id;
COMMIT;
out_code := '00';
out_desc := 'Success';
ELSE
out_code := '01';
out_desc := 'Already active';
END IF;
END sp_sample;
And this is how I call the stored proc in codeigniter:
$id = '10';
$params = array($id);
$result = $this->db->query("CALL sp_sample(?, #out_code, #out_desc)", $params);
exit($result);
Then I get this error message:
Query error: ORA-00936: missing expression - Invalid query: CALL sp_sample('10', #out_code, #out_code)
My question now is how can I call the oracle stored procedure using codeigniter? How to bind the parameters correctly?
Thanks,
Irvin

delete rows from a table based on table name and id?

I am giving two parameters as tlb_name for table name and id as id for deleting the row. Somehow it is not showing any error but after the execution of stored procedure, that particular row was not deleted from table.
`begin
if tlb_name='patients'
then
select 'YES';
set #t1=CONCAT("delete from" ,tlb_name, " where id= ? ");
set #id := id;
PREPARE stmt3 from #t1;
EXECUTE stmt3 USING #id;
DEALLOCATE PREPARE stmt3;
else
select 'Invalid User !!!!' ;
end if;
end`

How to optimise this temporary table query?

I have written a stored procedure that takes comma separated value as input and another value. I traverse values from comma separated value and then run a query for each value. now I need to return result so I thought to store results in temporary table and then selected values from that temporary table.But it is taking too long.
for query with 163 comma separated values it is taking 7 seconds.
for query with 295 comma separated values it is taking 12 seconds.
Here is procedure:-
DELIMITER $
create procedure check_fbid_exists(IN myArrayOfValue TEXT, IN leaderID INT(11) )
BEGIN
DECLARE status TINYINT(1);
DECLARE value INT(11);
DECLARE pos int(11);
CREATE TEMPORARY TABLE fbid_exists_result (userID int(11), status tinyint(1));
WHILE (CHAR_LENGTH(myArrayOfValue) > 0)
DO
SET pos=LOCATE( ',', myArrayOfValue);
IF pos>0 THEN
SET value = LEFT( myArrayOfValue,pos-1 );
SET myArrayOfValue= SUBSTRING( myArrayOfValue,pos+1 );
ELSE
SET value = myArrayOfValue;
SET myArrayOfValue='';
END IF;
SELECT EXISTS(SELECT 1 FROM users_followings WHERE UserID=value and LeaderUserID=leaderID LIMIT 1) INTO status;
insert into fbid_exists_result VALUES(value,status);
END WHILE;
SELECT * FROM fbid_exists_result ;
DROP TEMPORARY TABLE IF EXISTS fbid_exists_result ;
END$

After SP Insert, next page have an empty result until reloaded

I have a Stored Procedure (SP from now on) that inserts data to the database (SaveClient, see below). When the SP is done I redirect the PHP page to a different PHP page that lists the entries (FetchObjectList, see below). The list does not return the newly created record until I then reload/refresh the page.
The stored procedure has a COMMIT at the end, I close the database connection in the PHP code after the SP is called and there is a check for errors but nothing goes wrong.
The page itself returns a 200 statuscode which means it isn't cached so can't be browserrelated either.
The current workaround is a sleep(1) in the PHP code but when the code goes live I have no idea if it will suffice. I'd ofcourse rather have MySQL dish out the correct resultset.
EDIT: I'm using the MySQLi object interface of PHP, might be useful to know. ;)
My devcomputer got PHP 5.2.17, MySQL 5.0.51a (InnoDB) and Apache 2.2.17 installed and running on Windows 7 x64.
UPDATE
Added the following line CALL FetchObjectList('client_tbl', NULL, NULL, 1, 'client_tbl.name ASC', NULL, NULL); to the end of SaveClient. The resultset does not have the newly created client in the presented resultset.
UPDATE 2
I tried using the SQL_NO_CACHE as seen here but to no avail.
I will now try the same SQL directly in PHP instead of calling the SPs.
UPDATE 3 - 20 september
I've tried any reasonable answer/comment I've got so far without any luck. I tried to update my PHP and MySQL version today (since I today learned that the live server will run on PHP 5.3.something and MySQL 5.1.something) but did not get it to work. I need to update the PHP to get a more recent php_mysqli.dll/libmysql.dll since the one I got has only supports up to 5.0.51a and there might be my problem since nothing in the actual DB has worked. I tried the libmysql.dll from the MySQL install to no avail.
Note that I also changed the PHP code that I've included since I actually copied the wrong one that was calling the user_tbl and not the client_tbl and also simplified it (removed multiqueries) but still the same result.
I don't know what will happen to the bounty, if it reverts back to me I'll add it again.
Stored Procedure SaveClient
DELIMITER //
DROP PROCEDURE IF EXISTS work.SaveClient//
CREATE PROCEDURE work.SaveClient(
IN ObjectID INT,
IN UserID INT,
IN ClientName VARCHAR(60),
IN VersionFrom DATETIME,
IN VersionTo DATETIME)
root:BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
/*
Default values ---------------------------------------------------------------------------------------------------------
*/
# Used to block INSERT/UPDATEs
SET #DoChanges = TRUE;
SET #Fields = '*';
SET #Version = NULL;
SET #UserVersion = NULL;
SET #DateNow = NOW();
SET #VersionActive = CONCAT(
'( ( NOW() BETWEEN ',
'version_from AND ',
'version_to ) OR ( ',
'version_from < NOW() AND ',
'version_to IS NULL ) )'
);
IF VersionFrom IS NULL THEN
SET VersionFrom = #DateNow;
END IF;
/*
Search for client ------------------------------------------------------------------------------------------------------
*/
IF ObjectID IS NOT NULL THEN
SET #Client = CONCAT(
'SELECT version INTO #Version FROM client_tbl WHERE object_id = ',
ObjectID,
' AND ',
#VersionActive
);
PREPARE stmt FROM #Client;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# Check if there are any changes
IF #Version IS NOT NULL THEN
SELECT name INTO #Name FROM client_tbl WHERE name = ClientName AND version = #Version;
IF #Name = ClientName THEN
SET #errorMsg = "Duplicate entry";
SET #errorCode = "S0000002";
SELECT #errorCode, #errorMsg;
LEAVE root;
END IF;
END IF;
END IF;
/*
Search for user ---------------------------------------------------------------------------------------------------------
*/
# Create this as a function
IF UserID IS NOT NULL THEN
SET #User = CONCAT(
'SELECT version INTO #UserVersion FROM user_tbl WHERE object_id = ',
UserID,
' AND ',
#VersionActive
);
PREPARE stmt FROM #User;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
IF #UserVersion IS NULL THEN
SET #errorMsg = "User is missing";
SET #errorCode = "U0000099";
SELECT #errorCode, #errorMsg;
LEAVE root;
END IF;
/*
Add the client ---------------------------------------------------------------------------------------------------------
*/
# Close the current version
IF #Version IS NOT NULL THEN
IF #DoChanges = TRUE THEN
CALL UpdateVersion(
ObjectID,
UserID,
#Version,
#DateNow,
'client_tbl'
);
SET #Version = #Version + 1;
END IF;
ELSE
SET #Version = 1;
END IF;
IF #DoChanges = TRUE THEN
IF ObjectID IS NULL THEN
INSERT INTO
object_tbl
(
object_class_id,
created,
created_by
)
VALUES(
2,
NOW(),
UserID
)
;
SET ObjectID = LAST_INSERT_ID();
END IF;
INSERT INTO
client_tbl
(
object_id,
version,
version_from,
version_to,
changed,
changed_by,
name
)
VALUES(
ObjectID,
#Version,
VersionFrom,
NULL,
#DateNow,
UserID,
ClientName
)
;
END IF;
COMMIT;
END //
DELIMITER ;
Stored Procedure FetchObjectList
DELIMITER //
DROP PROCEDURE IF EXISTS work.FetchObjectList//
CREATE PROCEDURE work.FetchObjectList(
IN ObjectType VARCHAR(60),
IN ObjectSubType VARCHAR(60),
IN ObjectSubID INT,
IN IsActive INT,
IN OrderBy VARCHAR(100),
IN SetStart INT,
IN MaxResults INT)
root:BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
# Allow the "JSON" output be a max of 8kb
SET GLOBAL group_concat_max_len = 8096;
/*
Default values ---------------------------------------------------------------------------------------------------------
*/
SET #Fields = '*';
SET #VersionWhere = '1'; # Get everything
SET #Special = '';
SET #OrderBy = '';
SET #SetStart = '';
SET #MaxResults = '';
SET #JoinIn = '';
IF IsActive = 1 THEN
SET #VersionWhere = CONCAT(
'( NOW() BETWEEN ',
ObjectType,
'.version_from AND ',
ObjectType,
'.version_to OR ( ',
ObjectType,
'.version_from < NOW() AND ',
ObjectType,
'.version_to IS NULL ) )'
);
END IF;
IF OrderBy != '' THEN
SET #OrderBy = CONCAT(
'ORDER BY ',
OrderBy
);
END IF;
/*
Specials for each type -------------------------------------------------------------------------------------------------
*/
/*
- Clients ------------
*/
IF ObjectType = 'client_tbl' THEN
SET #Fields = '
*,
client_tbl.object_id AS object_id,
(
SELECT
COUNT(*) AS Total
FROM
client_user_privilege_tbl cup
WHERE
cup.client_id = client_tbl.object_id
) AS usercount
';
END IF;
/*
- Configuration ------------
*/
IF ObjectType = 'configuration_tbl' THEN
SET #Fields = '
*
';
END IF;
/*
Add upp the query to run -----------------------------------------------------------------------------------------------
*/
SET #Query = CONCAT(
'SELECT ',
#Fields,
' FROM ',
ObjectType,
' ',
#JoinIn,
' WHERE ',
#VersionWhere,
' ',
#Special,
#OrderBy
);
PREPARE stmt FROM #Query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
COMMIT;
END //
DELIMITER ;
PHP CODE SNIPPET (Updated 20 september)
$query = "CALL FetchObjectList('client_tbl', NULL, NULL, 1, NULL, NULL, NULL)";
addTrace($query);
$rs = $db->query($query);
if( $rs ) {
addTrace('Query done -> Results: ' . $rs->num_rows);
while($r = $rs->fetch_assoc()){
$fetchArray[] = $r;
}
$count = $rs->num_rows;
$rs->close();
$db->next_result();
} else {
addTrace('Query failed -> ' . $db->error);
flushTrace();
exit;
}
Since it's a pretty aged version of mysql it would not surprise me that this would be bug related but one thing I would -in your place- want to know is if this would work by not using transactions at all. (e.g. autocommit = on).
For that version 5.0 I would also check the query cache and disable it all together instead of per query (see SHOW VARIABLES LIKE 'have_query_cache'; SET GLOBAL query_cache_size =0; ). That would at the least eliminate those playing a role in this problem, reproduce(or try) the problem and see if anything changed. If not, I would start searching for specific bugs, especially when the query cache is disabled and it still does this without using transactions.
I verified the support for 5.0 mysql (innodb).
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
Set these options specifically in your my.cnf, the top one is most important. They explain nicely what those do.
See http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit
The problem with mysql_query is that it does not support multiple resultsets. And that is exactly what your stored procedures do – they tend to return more than one resultset. Whenever you call an SP, the exit status is secretly carried in an (empty) resultset along. If you add it up with your own output from a procedure, some of the resultsets from the query will be ignored by your PHP retrieval code. When you try to run another query, the pending resultset(s) will still be in the buffer.

Categories