Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

insight's avatar

How to make the dynamic query in loop to stored procedure ?

Dear Friends, I am using Laravel 10, MariaDB for my web application. My working code snippet as

 $phver = [];
                $phaseVersions = '';
                $phaseMasterData = PhaseMasterModel::orderBy('created_at', 'desc')->get();

                foreach ($phaseMasterData as $ph) {
                    $phase = $ph->phase;
                    $start_date = $ph->start_date;
                    $end_date = $ph->end_date;
                    $versionMasterData = VersionMasterModel::where('phase', $phase)->select('version')->get();
                    $phver = $versionMasterData->pluck('version')->toArray();

                    if (!empty($phver)) {
                        $phaseVersions = implode("','", $phver);
                        $query = "update " . $gen_table_name . " set phase = ? where eid_timestamp > '2019-12-31' and version in ('" . $phaseVersions . "')";
                        $genUpdate1 = DB::update($query, [$phase]);
                        $genUpdate2 = DB::table($gen_table_name)
                            ->where('eid_timestamp', '>=', $start_date)
                            ->where('eid_timestamp', '<=', $end_date)
                            ->whereNotIn('phase', [$phase])
                            ->update(['phase' => $phase]);
                       
                    }
                }

The above code works fine . But I need to create a PROCEDURE in MariaDB for same purpose . I created procedure as

DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `update_phases_on_upload`(
    IN phase VARCHAR(255),
    IN start_date DATE,
    IN end_date DATE,
    IN gen_table_name VARCHAR(255),
    IN phase_versions VARCHAR(255)
)
BEGIN
    DECLARE query VARCHAR(1000);
    SET @query = '';
    IF phase_versions IS NOT NULL THEN
        SET @query = CONCAT('UPDATE ', gen_table_name, ' SET phase = ? WHERE eid_timestamp > ''2019-12-31'' AND version IN (''', phase_versions, ''')');
        PREPARE stmt FROM @query;
        EXECUTE stmt USING phase;
        DEALLOCATE PREPARE stmt;
    END IF;
    SET @query = CONCAT('UPDATE ', gen_table_name, ' SET phase = ? WHERE eid_timestamp >= ? AND eid_timestamp <= ? AND phase <> ?');
    PREPARE stmt FROM @query;
    SET @phase = phase;
    SET @start_date = start_date;
    SET @end_date = end_date;
    EXECUTE stmt USING @phase, @start_date, @end_date, @phase;
    DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;

I changed my above controller code as

 $phver = [];
                $phaseVersions = '';
                $phaseMasterData = PhaseMasterModel::orderBy('created_at', 'desc')->get();

                foreach ($phaseMasterData as $ph) {
                    $phase = $ph->phase;
                    $start_date = $ph->start_date;
                    $end_date = $ph->end_date;
                    $versionMasterData = VersionMasterModel::where('phase', $phase)->select('version')->get();
                    $phver = $versionMasterData->pluck('version')->toArray();

                    if (!empty($phver)) {
                        $phaseVersions = implode("','", $phver);
                         DB::unprepared('CALL update_phases_on_upload(?, ?, ?, ?, ?)', [
                            $phase,
                            $start_date,
                            $end_date,
                            $gen_table_name,
                            $phaseVersions, 
                        ]);
                    }
                }

But I got error as

 "message": "SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?, ?, ?, ?, ?)' at line 1 (Connection: mysql, SQL: CALL update_phases_on_upload(?, ?, ?, ?, ?))",
    "exception": "Illuminate\Database\QueryException",
    "file": "C:\xampp\htdocs\akshaya_payment\vendor\laravel\framework\src\Illuminate\Database\Connection.php",
    "line": 793,
    "trace": [
        {
            "file": "C:\xampp\

My table schema I trying to update is as


CREATE TABLE `gen_jan2025_mar2025` (
  `sl` int(10) UNSIGNED NOT NULL,
  `eid` varchar(40) NOT NULL,
  `reg_id` varchar(5) DEFAULT NULL,
  `EA` int(11) DEFAULT NULL,
  `State_Name` varchar(20) DEFAULT NULL,
  `State_code` varchar(20) DEFAULT NULL,
  `District_Name` varchar(20) DEFAULT NULL,
  `District_code` varchar(20) DEFAULT NULL,
  `pincode` varchar(10) DEFAULT NULL,
  `version` varchar(10) DEFAULT NULL,
  `mcid` varchar(5) NOT NULL,
  `month` int(11) NOT NULL,
  `year` int(11) NOT NULL,
  `phase` char(2) DEFAULT '0',
  `eid_timestamp` date NOT NULL,
  `cut_date` date DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

updating dynamic table schema is as below


CREATE TABLE `gen_jan2025_mar2025` (
  `sl` int(10) UNSIGNED NOT NULL,
  `eid` varchar(40) NOT NULL,
  `reg_id` varchar(5) DEFAULT NULL,
  `EA` int(11) DEFAULT NULL,
  `State_Name` varchar(20) DEFAULT NULL,
  `State_code` varchar(20) DEFAULT NULL,
  `District_Name` varchar(20) DEFAULT NULL,
  `District_code` varchar(20) DEFAULT NULL,
  `pincode` varchar(10) DEFAULT NULL,
  `version` varchar(10) DEFAULT NULL,
  `mcid` varchar(5) NOT NULL,
  `month` int(11) NOT NULL,
  `year` int(11) NOT NULL,
  `phase` char(2) DEFAULT '0',
  `eid_timestamp` date NOT NULL,
  `cut_date` date DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

How to solve above issue. Please advise

Thanks

Anes P A

0 likes
11 replies
Snapey's avatar

I need to create a PROCEDURE in MariaDB

because ...... ?

insight's avatar

I saw it will improve performance according to popai.pro

In the provided code snippet, considering the scenario where you are looping through PhaseMasterModel records and performing updates based on conditions, using a stored procedure in this context can offer several advantages:

1. **Performance Efficiency**:
   - A stored procedure can execute multiple queries in a single trip to the database, reducing the number of round trips and potentially improving performance.
   
2. **Code Modularity**:
   - Stored procedures encapsulate logic, making it reusable and easier to maintain. It separates the business logic from application code.

3. **Reduced Network Traffic**:
   - By executing operations on the database server side, stored procedures can reduce network traffic compared to executing individual queries in a loop.

4. **Security and Permissions**:
   - Stored procedures can provide a layer of security by controlling access to specific database operations, enhancing data security.

For your scenario, considering the complexity and the multiple database operations being performed within the loop, using a stored procedure could be beneficial. It can streamline the process, enhance performance, and improve code maintainability in the long run. 

However, it's essential to carefully weigh the trade-offs and consider factors such as development time, maintainability, and existing infrastructure before deciding to migrate the logic to a stored procedure.

Please advise

Thanks

Anes P A

Tray2's avatar

I see no need to do this, is there a particular reason that you need to do it inside the database with a stored procedure?

insight's avatar

@Tray2 I hope it will reduce network traffic and my bose insist to do like that .

Tray2's avatar

@insight I write a lot of PL/SQL, the Oracle equvilelant of MariaDB's PL, but I never seen anyone use prepared statements like that.

Snapey's avatar

How many records in $phaseMasterData ?

How often do you need to perform this function?

Can the data be stored correctly in the first place?

insight's avatar

@Snapey There is only 45 rows in $phaseMasterData currently. But it is a growing table . This operation need to done weekly . Yes in current situation it stored correctly. That updating table is currently have 1 lakh rows . I will provide the schema of that table in my original question above. Please look and help.

Thanks

Anes P A

Snapey's avatar

@insight For something that runs once per week, and can be run at any time, do it in the simplest manner possible.

insight's avatar

@Snapey But my concern is procedure follow a transaction strategy but my normal method is not like that. I prefer a transaction supporting PROCEDURE than my normal method.

Thanks

Anes P A

insight's avatar

If it's not possible or not good , any other method to implement transaction for above normal query. If not fully executed the changes must rollback.. Please advise..

Thanks

Anes P A

insight's avatar

Dear Team, At last I think a transaction can implement my need . So I put that loop inside a transaction as shown in code

  $phver = [];
                $phaseVersions = '';
                $phaseMasterData = PhaseMasterModel::orderBy('created_at', 'desc')->get();
                DB::transaction(function () use ($phaseMasterData, $gen_table_name) {
                foreach ($phaseMasterData as $ph) {
                    $phase = $ph->phase;
                    $start_date = $ph->start_date;
                    $end_date = $ph->end_date;
                    $versionMasterData = VersionMasterModel::where('phase', $phase)->select('version')->get();
                    $phver = $versionMasterData->pluck('version')->toArray();
                    if (!empty($phver)) {
                        $phaseVersions = implode("','", $phver);
                        $query = "update " . $gen_table_name . " set phase = ? where eid_timestamp >= ? and eid_timestamp <= ? and version in (?)";
                        $genUpdate1 = DB::update($query, [$phase, $start_date, $end_date, $phaseVersions]);
                        $genUpdate2 = DB::table($gen_table_name)
                            ->where('eid_timestamp', '>=', $start_date)
                            ->where('eid_timestamp', '<=', $end_date)
                            ->whereNotIn('phase', [$phase])
                            ->update(['phase' => $phase]);
                    }
                }
            });

It works fine .

Thanks

Anes P A

1 like

Please or to participate in this conversation.