DECLARE syntax in MySQLi Query | When To DECLARE variables in Query - php

Apologies if posted already.
Searched a lot on google but I'm not understanding how to use DECLARE syntax in MySQL Query.
I'm not expert in MySQL. I'm seeing these codes on internet for DECLARE syntax. Not seen complete query anywhere.
DECLARE #destlist varchar(max)
SET #destlist = SELECT destinations FROM tbl_rings_to_groups WHERE id = '1' AND user_id = '1'
SELECT count( id ) AS totalDestination, group_concat( ring_to_number ) AS phoneNumbers
FROM tbl_destinations
WHERE id IN (CONCAT('SELECT ', REPLACE(#destlist), ',', ' UNION ALL SELECT '))
I'm using this for fetch results.
$result = $db->query("select from
table where something =
somethingElse order by something");
Now, how to use DECLARE in above code.
I'm trying this.
$result = $db->query(" DECLARE #destlist varchar(max)
SET #destlist = SELECT destinations FROM tbl_rings_to_groups WHERE id = '1' AND user_id = '1'
SELECT count( id ) AS totalDestination, group_concat( ring_to_number ) AS phoneNumbers
FROM tbl_destinations
WHERE id IN (CONCAT('SELECT ', REPLACE(#destlist), ',', ' UNION ALL SELECT '))");
Is this correct way to using MySQL DECLARE?

Related

MERGE INTO USING from dual (ORA-00923 FROM keyword not found where expected)

My query below was working, I swear... now suddenly, it's dead, outputting 'ORA-00923 FROM keyword not found where expected'.. I cannot understand why... I have tried various linters and syntax checkers; I am simply iterating through array data and pushing to a oracle table/row - adding a new entry if table_id is not found, and updating table_id if it is found. What am I missing?
Data coming in is perfect too.. what am I doing incorrectly..
$fd = json_decode($df, true);
foreach ($fd as $key=>$data) {
var_dump($data);
$sql = "MERGE INTO app.table a
using (SELECT '${data[0]}' table_id,
'${data[1]}' fac_ident,
'${data[2]}' lg_name,
'${data[3]}' basic_tp,
'${data[4]}' catc_vd,
'${data[5]}' address,
'${data[6]}' assoc_city,
'${data[7]}' latitude,
'${data[8]}' longitude,
'${data[9]}' assoc_cnty,
'${data[10]}' assoc_st,
'${data[11]}' time_zone,
FROM dual) p
ON ( a.table_id = p.table_id )
WHEN matched THEN
UPDATE SET a.fac_ident = p.fac_ident,
a.lg_name = p.lg_name,
a.basic_tp = p.basic_tp,
a.catc_vd = p.catc_vd,
a.address = p.address,
a.assoc_city = p.assoc_city,
a.latitude = p.latitude,
a.longitude = p.longitude,
a.assoc_cnty = p.assoc_cnty,
a.assoc_st = p.assoc_st,
a.time_zone = p.time_zone,
WHEN NOT matched THEN
INSERT (table_id,
fac_ident,
lg_name,
basic_tp,
catc_vd,
address,
assoc_city,
latitude,
longitude,
assoc_cnty,
assoc_st,
time_zone)
VALUES (p.table_id,
p.fac_ident,
p.lg_name,
p.basic_tp,
p.catc_vd,
p.address,
p.assoc_city,
p.latitude,
p.longitude,
p.assoc_cnty,
p.assoc_st,
p.time_zone)";
..........
If your data contains a single quote then you are doing the equivalent of trying to perform an SQL injection attack.
Don't use variable parsing ${data[0]}; instead create your query using bind variables and pass in your data properly so you are not vulnerable to SQL injection attacks.
For example:
If you have the table:
CREATE TABLE table_name (
table_id VARCHAR2(100),
fac_ident VARCHAR2(100)
)
And you have a table_id of 1 and a fac_ident of 2 then your merge would be:
MERGE INTO table_name a
USING (
SELECT '1' table_id,
'2' fac_ident
FROM dual
) p
ON ( a.table_id = p.table_id )
WHEN matched THEN
UPDATE SET a.fac_ident = p.fac_ident
WHEN NOT matched THEN
INSERT (table_id, fac_ident )
VALUES (p.table_id, p.fac_ident );
This works.
However, if fac_ident has the value This value has a 'quote' inside it. then your query is:
MERGE INTO table_name a
USING (
SELECT '1' table_id,
'This value has a 'quote' inside it.' fac_ident
FROM dual
) p
ON ( a.table_id = p.table_id )
WHEN matched THEN
UPDATE SET a.fac_ident = p.fac_ident
WHEN NOT matched THEN
INSERT (table_id, fac_ident )
VALUES (p.table_id, p.fac_ident );
And fails with:
ORA-00923: FROM keyword not found where expected
More insidious, is if fac_indent has the value '||(SELECT secret_column FROM secret_data WHERE ROWNUM = 1)||' and then your query becomes:
MERGE INTO table_name a
USING (
SELECT '1' table_id,
''||(SELECT secret_column FROM secret_data WHERE ROWNUM = 1)||'' fac_ident
FROM dual
) p
ON ( a.table_id = p.table_id )
WHEN matched THEN
UPDATE SET a.fac_ident = p.fac_ident
WHEN NOT matched THEN
INSERT (table_id, fac_ident )
VALUES (p.table_id, p.fac_ident );
And, if the table SECRET_DATA exists and has the column SECRET_COLUMN then your query won't fail and users can start to do unexpected things with your query. Please don't let them do this and use best practice of formulating your queries using bind variables rather than string concatenation.
db<>fiddle here

Mysql higher LIMIT offset very slow with join in PHP

I'm trying to change mySQL query for a faster data retrieval from the server. I have a table with more than 500,000 records but it takes forever to retrieve the data.
I want to change the query from
SELECT
loanapply.loanapplyId,
loanapply.loanAmount,
loanapply.email,
loanapply.approve,
loanapply.loanDate,
mkopakenya.name,
mkopakenya.idno,
mkopakenya.phoneNo,
mkopakenya.verification
FROM
loanapply
LEFT JOIN mkopakenya ON loanapply.email = mkopakenya.email
WHERE
loanapply.approve = 'ongoing'
AND loanapply.del = 'false'
AND loanapply.archive = 0
AND loanapply.loanDate = '$date'
GROUP BY
loanapply.loanapplyId,
loanapply.loanAmount,
loanapply.email,
loanapply.approve,
loanapply.loanDate,
mkopakenya.name,
mkopakenya.idno,
mkopakenya.phoneNo,
mkopakenya.verification
ORDER BY
loanapplyId DESC
LIMIT
$currentSize,
$limit
to
SELECT
loanapply.loanapplyId,
loanapply.loanAmount,
loanapply.email,
loanapply.approve,
loanapply.loanDate,
mkopakenya.name,
mkopakenya.idno,
mkopakenya.phoneNo,
mkopakenya.verification
FROM
loanapply
LEFT JOIN mkopakenya ON loanapply.email = mkopakenya.email AS data1
INNER JOIN (
SELECT
loanapply.loanapplyId
FROM
loanapply
LIMIT
$currentSize,
$limit
) AS data2 ON data1.loanapplyId = data2.loanapplyId
WHERE
loanapply.approve = 'ongoing'
AND loanapply.del = 'false'
AND loanapply.archive = 0
AND loanapply.loanDate = '$date'
ORDER BY
loanapplyId DESC
for faster data retrieval, The second query only returns blank values
for fast data retrival first you should check for valid indexes
be sure you have a proper composite index on loanapply eg:
create index myidx on loanapply ( loanDate, archive, del, approve, email )
and
table mkopakenya column ( email)
anyway (not for better perfomance but for proper use of SQL) you should not use group by without aggregation function (this behaviour is allowed for mysql version <5.7 but, by default, produce error for version >= 5.7) if you need distinct result use DISTINCT clause
SELECT DISTINCT loanapply.loanapplyId
, loanapply.loanAmount
, loanapply.email
, loanapply.approve
, loanapply.loanDate
, mkopakenya.name
, mkopakenya.idno
, mkopakenya.phoneNo
, mkopakenya.verification
FROM loanapply
LEFT JOIN mkopakenya ON loanapply.email = mkopakenya.email
WHERE loanapply.approve='ongoing'
AND loanapply.del='false'
AND loanapply.archive=0
AND loanapply.loanDate='$date'
ORDER BY loanapplyId DESC LIMIT $currentSize, $limit

Sphinx best way WHERE and UPDATE on MySql table

I kind used in MySQL query:
UPDATE
Tovar
Tovar INNER JOIN (
SELECT * FROM (.....
SELECT * FROM
....) as `tmp` ON
CONCAT(' ',Tovar.drugApt,' ') LIKE CONCAT('% ',tmp.`P`,' %')
OR IF(
tmp.line is not null,
CONCAT(' ',Tovar.drugApt,' ') LIKE CONCAT('% ',tmp.`line`,' %'),
0
) OR IF(
tmp.invert is not null,
CONCAT(' ',Tovar.drugApt,' ') LIKE CONCAT('% ',tmp.`invert`,' %'),
0
)
WHERE
Tovar.idPreparat IS NULL
AND Tovar.md5Drug <> 0xF7270DB295EE1770CAD49A0CB0C40D91
) tmpf ON tmpf.idT = Tovar.id
SET Tovar.idPreparat = tmpf.id;
As is well-known mysql doesn't use index:
WHERE LIKE '%....%'
Slow performance.
Then I have decided to try Fulltext index in mysql, but I don't accept performance time.
Now I have passed to Sphinx. Since I work in him for the first time, I ask to help.
table Tovar:
id, idPreparat, idCountry, idManufacturer, drugA, countryA, manfA
table Preparat:
id, prep
Tovar.idPreparat associated with Preparat.id
I create two Index in Sphinx:
source tovar : apt
{
sql_query = SELECT Tovar.id as id, Tovar.drugApt as drug,Tovar.countryApt as country,Tovar.manfApt as manf FROM Tovar
sql_field_string = drug
sql_field_string = country
sql_field_string = manf
sql_ranged_throttle = 100
}
source prep : apt
{
sql_query = SELECT id, prep FROM Preparat
sql_field_string = cn
sql_ranged_throttle = 100
}
I need to put down idPreparat where idPreparat IS NULL there. Check will be on the column drugA.
Example (everything is done by me, to make it clear):
What best way of realization of my problem? Thank!

MySQL get rows where corresponding row in same table exists

I'm trying to get rows from a table according to some basic where clauses, and now I want to include an "AND EXISTS" clause on the end. My code is the following:
$stmt = $mysqli->prepare("SELECT object_id FROM ".
$db_table_prefix."user_events
WHERE LPAD(start_timestamp,15,'0') < LPAD(?,15,'0')
AND event_id = ?
AND EXISTS (
SELECT * FROM ".$db_table_prefix."user_events
WHERE LPAD(start_timestamp,15,'0') > LPAD(?,15,'0')
AND event_id = ? )
");
The problem I'm having is that I don't know how to specify a column value from the main query within the AND EXISTS subquery.
I'm looking for a way to tack on this bit into the subquery:
AND object_id = **object_id from main query**
Any help appreciated
Also, added an alias to the subquery's table to avoid confusion
$stmt = $mysqli->prepare("SELECT object_id FROM ".
$db_table_prefix."user_events
WHERE LPAD(start_timestamp,15,'0') < LPAD(?,15,'0')
AND event_id = ?
AND EXISTS (
SELECT * FROM ".$db_table_prefix."user_events AS u
WHERE LPAD(u.start_timestamp,15,'0') > LPAD(?,15,'0')
AND u.object_id = " .$db_table_prefix.".object_id
AND u.event_id = ? )
");
Rather than EXISTS, you might find a self-join syntax is clearer here, I cannot deduce exactly what you want from your code, but to get object_id for an event that started before a specific time, and was also started again later:
SELECT ue1.object_id
FROM user_events ue1 join user_events ue2
WHERE ue1.event_id = ue2.event_id AND
ue1.object_id = ue2.object_id AND
ue1.event_id = ? AND
LPAD(ue1.start_timestamp, 15, '0') < LPAD(ue2.start_timestamp, 15, '0') AND
LPAD(ue1.start_timestamp, 15, '0') < LPAD(?, 15, '0')
and object_id in (select object_id from ...

MySQL query to select specific data

I would like to display the data that belongs to any of my users when they login to the site, as well as the name of each table (they completed offers on them).
This is the code I used, but when I add it it's not working.
$result = mysql_query('SELECT *,\'tbl1\' AS tablename FROM (SELECT * FROM table1 WHERE user_id='$user_id') as tbl1 UNION SELECT *,\'tbl2\' AS tablename FROM (SELECT * FROM table1 WHERE user_id='$user_id') as tbl2'. ' ORDER BY `date` DESC');
while($sdata = mysql_fetch_array($result)){
echo $sdata['date'];
echo $sdata['tablename'];
echo $sdata['user_reward'];
}
Where did I make a mistake?
You are missing the concatenation operators here, around $user_id:
$result = mysql_query(
'SELECT *,\'tbl1\' AS tablename FROM (
SELECT * FROM table1 WHERE user_id=' . $user_id . '
) as tbl1
UNION
SELECT *,\'tbl2\' AS tablename FROM (
SELECT * FROM table1 WHERE user_id=' . $user_id . '
) as tbl2' . ' ORDER BY `date` DESC'
);
I've wrapped the call for more clarity - I suggest you do the same in your own code. I'd be inclined to use " marks here instead, so you don't need to escape apostrophes.
The ORDER BY clause seems to be redundantly concatenated as well - remove the dot and add this part of the query to the as tbl2 part.
Here's how I would do it:
$sql = "
SELECT *, 'tbl1' AS tablename FROM (
SELECT * FROM table1 WHERE user_id={$user_id}
) as tbl1
UNION
SELECT *, 'tbl2' AS tablename FROM (
SELECT * FROM table1 WHERE user_id={$user_id}
) as tbl2
ORDER BY `date` DESC
";
$result = mysql_query($sql);
Make sure that $user_id is properly escaped or cast, to avoid security problems. Also, this database library is no longer recommended, and will be removed in a future version of PHP. It would be better to move to PDO or mysqli, and use parameterisation.
Finally, it does rather look like the query itself is rather cumbersome - it looks like it could be simplified. Perhaps ask a separate question on that?

Categories