Разликите могат да бъдат незначителни, понякога важни, а понякога на практика несъществуващи.
Като цяло подготвен оператор 1. се подготвя със сървъра (SQL анализиран, генериран план за изпълнение и т.н.), 2. се изпълнява с допълнителните параметри и след това 3. се затваря. Позволява ви да използвате повторно един и същ SQL с различни параметри, предавани всеки път, може да ви помогне да се предпазите от SQL инжектиране, може да осигури някои подобрения на производителността (специфични за драйвер/протокол, YMMV) и да предотврати повтарящи се стъпки, както при генериране на план за изпълнение и анализиране на SQL в подгответе стъпка по-горе.
За някой, който пише изходен код, подготвеното изявление може да е по-удобно от конкатенирането на низове и изпращането им до DB сървъра.
DB.Query()
методът приема SQL като низ и нула или повече аргументи (както и Exec()
или QueryRow()
). SQL низ без допълнителни аргументи ще потърси точно това, което сте написали. Въпреки това, при условие че има SQL низ с заместители и допълнителни аргументи, под капака се прави подготвено изявление за вас.
DB.Prepare()
методът изрично изпълнява подготвен израз, на който след това предавате аргументи, както е в:stmt.Exec(...args)
.
Има няколко неща, върху които си струва да помислите, по отношение на разликите между двете и защо да използвате едното или другото.
Можете да използвате DB.Query()
без аргументи. Това може да бъде много ефективно, тъй като може да заобиколи подготви --> изпълни --> затвори последователност, през която задължително преминава подготвеното изявление.
Можете също да го използвате с допълнителни аргументи и заместители в низа на заявката и той ще изпълни подготвен оператор под кориците, както споменах по-горе. Потенциалният проблем тук е, че когато правите няколко заявки, всяка от тях води до подготвено изявление под капака. Тъй като има допълнителни стъпки, това може да бъде доста неефективно, тъй като се подготвя отново, изпълнява и затваря всеки път, когато правите тази заявка.
С изрично подготвено изявление можете да избегнете тази неефективност, докато се опитвате да използвате повторно подготвения от вас SQL, с потенциално различни аргументи.
Но това не винаги се получава, както бихте очаквали... Поради основния пул за връзки, който се управлява от db/sql, вашата "връзка с база данни" е доста виртуална. DB.Prepare()
Методът ще подготви изявлението срещу конкретна връзка и след това ще се опита да върне същата връзка, когато е време за изпълнение, но ако тази връзка не е налична, тя просто ще вземе такава, която е налична, и ще подготви отново и ще се изпълни срещу нея. Ако използвате същото подготвено изявление отново и отново, тогава може, несъзнателно, да го подготвяте отново и отново. Това очевидно се появява най-вече, когато имате работа с натоварен трафик.
Така че очевидно кое за какви обстоятелства ще използвате зависи от конкретния ви случай на употреба, но се надявам подробностите по-горе да ви помогнат да ви изяснят достатъчно, за да можете да вземете най-доброто решение във всеки отделен случай.
Актуализиране
Като се има предвид актуализацията в OP, по същество няма разлика, когато заявката трябва да бъде изпълнена само веднъж, тъй като заявките с аргументи се извършват като подготвени оператори зад кулисите.
Използвайте директните методи, напр. DB.Query()
и неговите аналози, в сравнение с изричното използване на подготвени оператори, тъй като това ще доведе до малко по-опростен изходен код.
Тъй като в този случай подготвените изявления се използват от съображения за сигурност, може да си струва усилията да се справят с проблемите със сигурността с други средства и вместо това да се използват заявки в обикновен текст, тъй като това ще подобри производителността. Всички печалби обаче може да са без значение, освен ако няма достатъчно трафик (или се предвижда трафикът да нарасне значително в бъдеще), за да се наложи облекчаване на натоварването на сървъра. Отново се свежда до реалния случай на употреба.
За всеки, който се интересува от някои показатели за разликата между подготвени изявления и директни заявки в обикновен текст, има добра статия тук (което също върши отлична работа за обяснение на голяма част от горното).