CakeFest 2024: The Official CakePHP Conference

Hazır deyimler ve Saklı Yordamlar

Genellikle gelişkin veritabanlarınca desteklenen, hazır deyimler diye bilinen bir kavram vardır. Bunlar nedir? Bunları bir takım bağımsız değişkenlerle özelleştirilebilen, SQL için derlenmiş şablonlar olarak düşünebilirsiniz. Hazır deyimlerin başlıca iki yararı vardır:

  • Sorgunun tek bir defa çözümlenmesi (veya hazırlanması) gerekir fakat aynı veya farklı bağımsız değişkenlerle defalarca çalıştırılabilir. Sorgu hazır olduğunda veritabanınca incelenir, derlenip sorgunun amacına uygun olarak en iyilenir. Karmaşık sorgularda aynı sorguyu farklı bağımsız değişkenlerle defalarca yineleyecekseniz işlemler, uygulamanızı farkedilir şekilde yavaşlatacak kadar uzun sürebilir. Hazır deyimleri kullanarak her yinelemede tekrarlanan inceleme/derleme/eniyileme döngüsünden kurtulabilirsiniz. Özetle, hazır deyimler daha az özkaynak kullandığından daha hızlı çalışır.
  • Hazır deyim bağımsız değişkenlerinin öncelenmesi gerekmez. Bu işlemi sürücüler sizin yerinize yapar. Uygulamanız özellikle hazır deyimleri kullanıyorsa hiçbir SQL zerkinin olmayacağından emin olabilirsiniz. (Ancak, sorgunun diğer parçaları öncelenmemiş girdiler içeriyorsa hala risk altındasınız demektir.)

Hazır deyimleri kullanmanın bir başka yararı da bunları desteklemeyen sürücüler için PDO'nun bu özelliği taklit etmesidir (PDO'nun taklit ettiği tek özellik budur). Böylece aynı veri erişim uygulamasını veritabanınızın yeteneklerinden bağımsız olarak kullanabilirsiniz.

Örnek 1 - Hazır deyimlerle bağımsız değişken ismine göre veri girişi

Bu örnekte isim ve deger alanlarına bağımsız değişkenlerin isimlerine göre bir INSERT sorgusu ile defalarca veri girilmektedir.

<?php
$deyim
= $dbh->prepare(
"INSERT INTO KUTUK (isim, deger) VALUES (:isim, :deger)");
$deyim->bindParam(':isim', $isim);
$deyim->bindParam(':değer', $değer);

// bir satıra veri girelim
$isim = 'bir';
$değer = 1;
$deyim->execute();

// farklı değerlerle bir satır daha girelim
$isim = 'iki';
$değer = 2;
$deyim->execute();
?>

Örnek 2 - Hazır deyimlerle bağımsız değişken indisine göre veri girişi

Bu örnekte isim ve deger alanlarına bağımsız değişkenlerin indislerine göre bir INSERT sorgusu ile defalarca veri girilmektedir.

<?php
$deyim
= $dbh->prepare("INSERT INTO KUTUK (isim, değer) VALUES (?, ?)");
$deyim->bindParam(1, $isim);
$deyim->bindParam(2, $değer);

// bir satıra veri girelim
$isim = 'bir';
$değer = 1;
$deyim->execute();

// farklı değerlerle bir satır daha girelim
$isim = 'iki';
$değer = 2;
$deyim->execute();
?>

Örnek 3 - Hazır deyimle veri almak

Bu örnekte bir formdan sağlanan bir anahtar değere dayanarak veritabanından veri alınmaktadır. Kullanıcı girdisi otomatik olarak öncelenmekte, dolayısıya bir SQL zerki riski ortaya çıkmamaktadır.

<?php
$deyim
= $dbh->prepare("SELECT * FROM KUTUK where isim = ?");
$deyim->execute([$_GET['isim']]);
foreach (
$deyim as $satır) {
print_r($satır);
}
?>

Örnek 4 - Bir saklı yordamın çıktı bağımsız değişkeni ile kullanımı

Eğer veritabanı sürücüsü bağımsız değişken ilişkilendirmeyi destekiyorsa bağımsız değişkenleri sadece girdide değil çıktıda da bağımsız değişkenlerle ilişkilendirebilirsiniz. Çıktı bağımsız değişkenlerinin kullanımı girdi bağımsız değişkenlerine göre daha karmaşıktır. Böyle bir durumda ilişkilendirdiğiniz bağımsız değişken sayısını bilmeniz gerekir. Eğer dönen değer önerdiğinizden daha büyükse bir hata oluşur.

<?php
$deyim
= $dbh->prepare("CALL sy_dizge_döndürür(?)");
$deyim->bindParam(1, $dönen_değer, PDO::PARAM_STR, 4000);

// saklı yordamı çağıralım
$deyim->execute();

print
"dönen değer: $dönen_değer\n";
?>

Örnek 5 - Bir saklı yordamın girdi/çıktı bağımsız değişkeni ile kullanımı

Ayrıca, değerleri tutan bağımsız değişkenleri hem girdi hem de çıktı için kullanabilirsiniz. Sonraki örnekte, saklı yordama 'merhaba' dizgesi aktarılmakta, yordam döndüğünde 'merhaba' yerine yordamın dönüş değeri yerleştirilmektedir.

<?php
$deyim
= $dbh->prepare("CALL sy_dizge_alır_dizge_döndürür(?)");
$değer = 'merhaba';
$deyim->bindParam(1, $değer, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);

// saklı yordamı çağıralım
$deyim->execute();

print
"dönen değer: $değer\n";
?>

Örnek 6 - Geçersiz bağımsız değişken kullanımı

<?php
$deyim
= $dbh->prepare("SELECT * FROM KUTUK where isim LIKE '%?%'");
$deyim->execute([$_GET['isim']]);

// bağımsız değişken değerin bütünün yerine kullanılmalı
$deyim = $dbh->prepare("SELECT * FROM KUTUK where isim LIKE ?");
$deyim->execute(["%$_GET[isim]%"]);
?>

add a note

User Contributed Notes 4 notes

up
218
adam at pyramidpower dot com dot au
13 years ago
Note that when using name parameters with bindParam, the name itself, cannot contain a dash '-'.

example:
<?php
$stmt
= $dbh->prepare ("INSERT INTO user (firstname, surname) VALUES (:f-name, :s-name)");
$stmt -> bindParam(':f-name', 'John');
$stmt -> bindParam(':s-name', 'Smith');
$stmt -> execute();
?>

The dashes in 'f-name' and 's-name' should be replaced with an underscore or no dash at all.

See http://bugs.php.net/43130

Adam
up
12
w37090 at yandex dot ru
4 years ago
Insert a multidimensional array into the database through a prepared query:
We have an array to write the form:

$dataArr:
Array
(
[0] => Array
(
[0] => 2020
[1] => 23
[2] => 111111
)

[1] => Array
(
[0] => 2020
[1] => 24
[2] => 222222222
)
....

Task: prepare a request and pass through binds
$array = [];
foreach ($dataArr as $k=>$v) {
// $x = 2020, the variable is predetermined in advance, does not change the essence
$array[] = [$x, $k, $v];
}
$sql = ("INSERT INTO `table` (`field`,`field`,`field`) VALUES (?,?,?)");

$db->queryBindInsert($sql,$array);

public function queryBindInsert($sql,$bind) {
$stmt = $this->pdo->prepare($sql);

if(count($bind)) {
foreach($bind as $param => $value) {
$c = 1;
for ($i=0; $i<count($value); $i++) {
$stmt->bindValue($c++, $value[$i]);
}
$stmt->execute();
}
}
}
up
0
theking2(at)king.ma
1 month ago
Example #5 gives an 1414 wenn tried on MariaDB. Use this function to call a stored procedure with the last parameter as INOUT returning a value like a (uu)id or a count;

<?php
/**
* call_sp Call the specified stored procedure with the given parameters.
* The first parameter is the name of the stored procedure.
* The remaining parameters are the (in) parameters to the stored procedure.
* the last (out) parameter should be an int like state or number of affected rows.
*
* @param mixed $sp_name The name of the stored procedure to call.
* @param mixed $params The parameters to pass to the stored procedure.
* @return int The number of affected rows.
*/
function call_sp( \PDO $db, string $sp_name, ...$params ): mixed
{
$placeholders = array_fill( 0, count( $params ), "?" );
$placeholders[] = "@new_id";

$sql = "CALL $sp_name( " . implode( ", ", $placeholders ) . " ); SELECT @new_id AS `new_id`";

try {
LOG->debug( "calling Stored Procedure", [ "sql" => $sql ] );

$stmt = $db->prepare( $sql );
$i = 0;
foreach(
$params as $param ) {
$stmt->bindValue( ++$i, $param );
}
$stmt->execute();
$new_id = $stmt->fetch( PDO::FETCH_ASSOC )['new_id'];

return
$new_id;

} catch (
\Exception $e ) {
LOG->error( "Error calling Stored Procedure", [ "sql" => $sql, "params" => $params, "error" => $e->getMessage() ] );
throw
$e;
}
up
-59
bkilinc at deyta dot net
3 years ago
it is a good practice not using double quotes in sql strings. This way you can ensure that no variable is injected in query.
a simple query with parameters should be;
'INSERT INTO REGISTRY (name, value) VALUES (?, ?)'
not
"INSERT INTO REGISTRY (name, value) VALUES (?, ?)"
To Top