Прав­ду го­во­рил Ано­ни­мус: век жи­ви - век учись. Еще в вер­сии 4.1 в mysql по­яви­лась та­кая вещь, как prepared statements, а узнал я это толь­ко вче­ра, пере­ли­сты­вая от не­че­го де­лать уми­ра­ю­щий habrahabr - ста­тьи ста­ли за­нуд­ны­ми ко­пи­па­ста­ми и лю­би­тель­ски­ми пере­во­да­ми, но я не об этом. Что же это за сло­во­со­чи­та­ние, пере­ве­ден­ное Google Translate как "под­го­тов­лен­ные заяв­ле­ния" =)? На­вер­ня­ка, каж­дый, кто хоть раз за­ду­мы­вал­ся о за­щи­те сво­е­го при­ло­же­ния от инъ­ек­ций в ба­зу дан­ных, смот­рел в сто­ро­ну биб­лио­тек с с под­держ­кой placeholder-ов, а ока­за­лось, что все это мож­но де­лать не­по­сред­ствен­но син­так­си­сом mysql. Вот вам на за­мет­ку не­большой лик­без.Исполь­зо­ва­ние prepared statements да­ет не­пло­хой при­рост как к без­опастно­сти, так и к произ­во­ди­тель­но­сти. Что ка­са­ет­ся пер­во­го, то при подста­нов­ке пере­мен­ных в го­то­вый запрос сер­вер ав­то­ма­ти­че­ски экра­ни­ру­ет все сим­во­лы, что в прин­ци­пе сво­дит ве­ро­ят­ность ле­во­го UNION-а, JOIN-а, ли­бо дру­гой па­ко­сти к ну­лю. Что ка­са­ет­ся ско­ро­сти, то тут то­же есть свои ин­терес­но­сти. Во-пер­вых, при много­крат­но по­вто­ря­ю­щих­ся од­но­тип­ных запро­сах зна­чи­тель­но ми­ни­ми­зи­ру­ет­ся траф­фик меж­ду про­грам­мой и сер­ве­ром БД, ну а во-вто­рых mysql про­ве­ря­ет син­так­сис запро­са и пар­сит его всего 1 раз, при ини­ци­а­ли­за­ции placeholder-а. Вы мо­же­те ис­поль­зо­вать дан­ный функ­ци­о­нал на INSERT, DELETE, UPDATE, SELECT и CREATE TABLE запро­сах. Ра­бо­та­ет, сле­дуя ма­ну­а­лу, это сле­ду­ю­щим об­разом. Сна­ча­ла под­го­тав­ли­ва­ем запрос для даль­ней­ше­го ис­поль­зо­ва­ния PREPARE getgoodprice FROM "SELECT `price` FROM `goods` WHERE `id`=?". По­сле это­го мо­жем подстав­лять зна­че­ния в плей­с­хол­дер, вы­пол­нив SET @goodid = 5. Эту пере­мен­ную мы и подстав­ляем в запрос EXECUTE getgoodprice USING @goodid, по­лу­чая ана­лог запро­са SELECT `price` FROM `goods` WHERE `id`=5. Вот так вот все про­сто. Ра­зу­ме­ет­ся, на еди­нич­ных query на­много луч­ше экра­ни­ро­вать пере­да­ва­е­мые зна­че­ния по­сред­ством функ­ции язы­ка про­грам­миро­ва­ния, но для мно­же­ства слож­ных запро­сов с несколь­ки­ми па­ра­мет­ра­ми вы­бор­ки ли­бо сор­ти­ров­ки PREPARE под­хо­дит на ура. Ах да, из па­мя­ти сохра­нен­ный запрос уда­ля­ет­ся по­сред­ством DEALLOCATE PREPARE getgoodpric.