<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="cs">
	<id>http://postgres.cz/index.php?action=history&amp;feed=atom&amp;title=Dynamick%C3%A9_SQL</id>
	<title>Dynamické SQL - Historie editací</title>
	<link rel="self" type="application/atom+xml" href="http://postgres.cz/index.php?action=history&amp;feed=atom&amp;title=Dynamick%C3%A9_SQL"/>
	<link rel="alternate" type="text/html" href="http://postgres.cz/index.php?title=Dynamick%C3%A9_SQL&amp;action=history"/>
	<updated>2026-05-12T21:52:41Z</updated>
	<subtitle>Historie editací této stránky</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>http://postgres.cz/index.php?title=Dynamick%C3%A9_SQL&amp;diff=226&amp;oldid=prev</id>
		<title>78.102.13.242 v 9. 12. 2008, 08:36</title>
		<link rel="alternate" type="text/html" href="http://postgres.cz/index.php?title=Dynamick%C3%A9_SQL&amp;diff=226&amp;oldid=prev"/>
		<updated>2008-12-09T08:36:49Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Nová stránka&lt;/b&gt;&lt;/p&gt;&lt;div&gt;=== EXECUTE IMMEDIATE ===&lt;br /&gt;
V SQL procedurach lze bezproblémově vkládat do kódu většinu SQL příkazů, které můžeme parametrizovat proměnnými. Parametr nelze &lt;br /&gt;
použít ve smyslu názvu sloupce nebo proměnné. Také nelze vložit např. SQL příkaz &amp;#039;&amp;#039;CREATE FUNCTION&amp;#039;&amp;#039;. Proto existuje tzv. &lt;br /&gt;
dynamické SQL - příkazy &amp;#039;&amp;#039;EXECUTE IMMEDIATE&amp;#039;&amp;#039; a &amp;#039;&amp;#039;EXECUTE&amp;#039;&amp;#039;. Příkaz &amp;#039;&amp;#039;EXECUTE IMMEDIATE&amp;#039;&amp;#039; provede libovolný SQL příkaz předaný &lt;br /&gt;
v řetězci. Výsledkem mohou být naplněné určené proměnné, pokud použijete klauzuli &amp;#039;&amp;#039;INTO&amp;#039;&amp;#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE OR REPLACE FUNCTION fx() &lt;br /&gt;
RETURNS int AS &lt;br /&gt;
$$&lt;br /&gt;
  BEGIN &lt;br /&gt;
    DECLARE a,b int; &lt;br /&gt;
    EXECUTE IMMEDIATE &amp;#039;SELECT 10,20&amp;#039; INTO a,b; &lt;br /&gt;
    PRINT a,b; &lt;br /&gt;
    RETURN a+b; &lt;br /&gt;
  END; &lt;br /&gt;
$$ LANGUAGE plpgpsm;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Syntaxe&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
EXECUTE IMMEDIATE vyraz [INTO (seznam promennych| promenna typu RECCORD nebo ROW)]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== PREPARE a EXECUTE ===&lt;br /&gt;
&amp;#039;&amp;#039;EXECUTE IMMEDIATE&amp;#039;&amp;#039; se nehodí pro opakované provádění SQL příkazu. Pokaždé se vytváří nový prováděcí plán, což v některých případech&lt;br /&gt;
může mít znatelně zpomalovat. Potom se vyplatí uvažovat o předzpracovaných SQL příkazech. Předzpracovaný SQL příkaz získáme příkazem&lt;br /&gt;
&amp;#039;&amp;#039;PREPARE&amp;#039;&amp;#039; a necháme jej provést příkazem &amp;#039;&amp;#039;EXECUTE&amp;#039;&amp;#039;. Můžeme použít klauzuli INTO pro uložení výsledku dotazu do proměnných. V případě,&lt;br /&gt;
že jsme použili parametrizovaný SQL příkaz (obsahuje symboly ? na pozicích parametrů) musíme předpřipravený SQL příkaz spouštět s parametry&lt;br /&gt;
předávanými prostřednictvím klauzule &amp;#039;&amp;#039;USING&amp;#039;&amp;#039;. Použitím parametrů eliminujeme riziko [[#SQL injection|SQL injection]].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE OR REPLACE FUNCTION fxx(a int)&lt;br /&gt;
RETURNS float AS &lt;br /&gt;
$$&lt;br /&gt;
  BEGIN&lt;br /&gt;
    DECLARE f float;&lt;br /&gt;
    PREPARE prep(float) from &amp;#039;select $1&amp;#039;;&lt;br /&gt;
    EXECUTE prep INTO f USING a; &lt;br /&gt;
    RETURN f ;&lt;br /&gt;
  END;&lt;br /&gt;
$$ LANGUAGE plpgpsm;&lt;br /&gt;
CREATE FUNCTION&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Syntaxe&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PREPARE nazev [ &amp;#039;(&amp;#039; seznam typu parametru &amp;#039;)&amp;#039; ] FROM vyraz &lt;br /&gt;
&lt;br /&gt;
EXECUTE nazev [INTO (seznam promennych | promenna typu RECORD nebo ROW)]&lt;br /&gt;
              [USING seznam promennych]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dynamické kurzory ==&lt;br /&gt;
Příkazy EXECUTE a EXECUTE IMMEDIATE neumožňují zpracovat více než jeden řádek. Proto byl příkaz OPEN rozšířen a umožňuje jako zdroj použít i předzpracovaný příkaz. Pokud předzpracovaný příkaz vyžaduje parametry, pak příkaz OPEN musí obsahovat klauzuli USING. Dynamické kurzory nelze použít jako posuvné kurzory.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE OR REPLACE FUNCTION fx(a int)                                                                                    &lt;br /&gt;
RETURNS int AS                                                                                                          &lt;br /&gt;
$$                                                                                                                      &lt;br /&gt;
#option dump                                                                                                            &lt;br /&gt;
  BEGIN                                                                                                                 &lt;br /&gt;
    DECLARE x, y integer;                                                                                               &lt;br /&gt;
    DECLARE SQLSTATE char(5);                                                                                           &lt;br /&gt;
                                                                                                                        &lt;br /&gt;
    DECLARE cx CURSOR FOR prepstmt;                                                                                     &lt;br /&gt;
                                                                                                                        &lt;br /&gt;
    PREPARE prepstmt(int) FROM &amp;#039;SELECT a*100, b*100 FROM Foo WHERE Foo.a = $1&amp;#039;;                                         &lt;br /&gt;
                                                                                                                        &lt;br /&gt;
    OPEN cx USING a;                                                                                                    &lt;br /&gt;
                                                                                                                        &lt;br /&gt;
    FETCH cx INTO x, y;                                                                                                 &lt;br /&gt;
    WHILE SQLSTATE = &amp;#039;00000&amp;#039; DO                                                                                         &lt;br /&gt;
      PRINT x, y;                                                                                                       &lt;br /&gt;
      FETCH cx INTO x, y;                                                                                               &lt;br /&gt;
    END WHILE;                                                                                                          &lt;br /&gt;
                                                                                                                        &lt;br /&gt;
    CLOSE cx;                                                                                                           &lt;br /&gt;
    RETURN a;                                                                                                           &lt;br /&gt;
  END;                                                                                                                  &lt;br /&gt;
$$ LANGUAGE plpgpsm;        &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SQL injection ===&lt;br /&gt;
SQL injection je jedním ze způsobů napadnutí SQL serveru. Útočník se pokusí pomocí parametrů modifikovat SQL příkaz tak, aby se&lt;br /&gt;
dostal k obsahu libovolné tabulky v databázi. Za normálních okolností jsou SQL procedury odolné vůči tomuto typu útoku díky &lt;br /&gt;
internímu používání předzpracovaných SQL příkazů (prepared statements). Dynamické SQL ale představuje pootevřená zadní vrátka, &lt;br /&gt;
kudy se útočník může do systému dostat. Dynamickému SQL se v řadě případů nevyhneme, nicméně je nutné pečlivě kontrolovat obsah&lt;br /&gt;
proměnných (nebo používat klauzuli USING).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  --nebezpecne, promenna _tab a _var predstavuji bezpecnostni riziko&lt;br /&gt;
  EXECUTE IMMEDIATE &amp;#039;SELECT * FROM &amp;#039;|| _tab || &amp;#039; WHERE a = &amp;#039;&amp;#039;&amp;#039; || _var ||&amp;#039;&amp;#039;&amp;#039; INTO _a, _b;&lt;br /&gt;
&lt;br /&gt;
  -- predstavuje bezpecnostni riziko, staci vsak jen test, zda _tab neobsahuje specialni znaky&lt;br /&gt;
  -- rizikem je pouze promenna _tab&lt;br /&gt;
  PREPARE psel(varchar) &amp;#039;SELECT * FROM &amp;#039; || _tab || &amp;#039;WHERE a = ?&amp;#039;;&lt;br /&gt;
  EXECUTE psel INTO _a, _b  USING _var;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>78.102.13.242</name></author>
	</entry>
</feed>