8000 Doc: improve discussion of variable substitution in PL/pgSQL. · postgres/postgres@c783e65 · GitHub
[go: up one dir, main page]

Skip to content
{"payload":{"commit":{"oid":"c783e656d41816b0328cb4bff27f11b70200770e","url":"/postgres/postgres/commit/c783e656d41816b0328cb4bff27f11b70200770e","authoredDate":"2021-03-17T13:09:13.000-04:00","committedDate":"2021-03-17T13:09:13.000-04:00","shortMessage":null,"shortMessageMarkdown":"\u003cdiv\u003eDoc: improve discussion of variable substitution in PL/pgSQL.\u003c/div\u003e","shortMessageMarkdownLink":null,"bodyMessageHtml":"This was a bit disjointed, partly because of a not-well-considered\ndecision to document SQL commands that don't return result rows as\nthough they had nothing in common with commands that do. Rearrange\nso that we have one discussion of variable substitution that clearly\napplies to all types of SQL commands, and then handle the question\nof processing command output separately. Clarify that EXPLAIN,\nCREATE TABLE AS SELECT, and similar commands that incorporate an\noptimizable statement will act like optimizable statements for the\npurposes of variable substitution. Do a bunch of minor wordsmithing\nin the same area.\n\nDavid Johnston and Tom Lane, reviewed by Pavel Stehule and David\nSteele\n\nDiscussion: \u003ca href=\"https://postgr.es/m/CAKFQuwYvMKucM5fnZvHSo-ah4S=_n9gmKeu6EAo=_fTrohunqQ@mail.gmail.com\" rel=\"nofollow\"\u003ehttps://postgr.es/m/CAKFQuwYvMKucM5fnZvHSo-ah4S=_n9gmKeu6EAo=_fTrohunqQ@mail.gmail.com\u003c/a\u003e","authors":[{"login":"tglsfdc","displayName":"Tom Lane","avatarUrl":"https://avatars.githubusercontent.com/u/8755309?v=4","path":"/tglsfdc","isGitHub":false}],"committerAttribution":false,"committer":{"login":"tglsfdc","displayName":"Tom Lane","avatarUrl":"https://avatars.githubusercontent.com/u/8755309?v=4","path":"/tglsfdc","isGitHub":false},"parents":["7f7f25f15edb6eacec58179ef5285e874aa4435b"],"globalRelayId":"MDY6Q29tbWl0OTI3NDQyOmM3ODNlNjU2ZDQxODE2YjAzMjhjYjRiZmYyN2YxMWI3MDIwMDc3MGU=","sha1":"7f7f25f15edb6eacec58179ef5285e874aa4435b","sha2":"c783e656d41816b0328cb4bff27f11b70200770e"},"currentUser":null,"repo":{"id":927442,"defaultBranch":"master","name":"postgres","ownerLogin":"postgres","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2010-09-21T11:35:45.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/177543?v=4","public":true,"private":false,"isOrgOwned":true},"diffEntryData":[{"diffLines":[{"stylingDirective":null,"type":"HUNK","blobLineNumber":893,"text":"@@ -894,7 +894,7 @@ SELECT \u003creplaceable\u003eexpression\u003c/replaceable\u003e","html":"@@ -894,7 +894,7 @@ SELECT \u0026lt;replaceable\u0026gt;expression\u0026lt;/replaceable\u0026gt;","displayNoNewLineWarning":false,"position":0,"left":893,"right":893},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":894,"text":" \u003c/synopsis\u003e","html":" \u0026lt;/synopsis\u0026gt;","displayNoNewLineWarning":false,"position":1,"left":894,"right":894},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":895,"text":" to the main SQL engine. While forming the \u003ccommand\u003eSELECT\u003c/command\u003e command,","html":" to the main SQL engine. While forming the \u0026lt;command\u0026gt;SELECT\u0026lt;/command\u0026gt; command,","displayNoNewLineWarning":false,"position":2,"left":895,"right":895},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":896,"text":" any occurrences of \u003capplication\u003ePL/pgSQL\u003c/application\u003e variable names","html":" any occurrences of \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; variable names","displayNoNewLineWarning":false,"position":3,"left":896,"right":896},{"stylingDirective":null,"type":"DELETION","blobLineNumber":897,"text":"- are replaced by parameters, as discussed in detail in","html":"- are replaced by parameters, as discussed in detail in","displayNoNewLineWarning":false,"position":4,"left":897,"right":896},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":897,"text":"+ are replaced by query parameters, as discussed in detail in","html":"+ are replaced by \u003cspan class=\"x x-first x-last\"\u003equery \u003c/span\u003eparameters, as discussed in detail in","displayNoNewLineWarning":false,"position":5,"left":897,"right":897},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":898,"text":" \u003cxref linkend=\"plpgsql-var-subst\"/\u003e.","html":" \u0026lt;xref linkend=\u0026quot;plpgsql-var-subst\u0026quot;/\u0026gt;.","displayNoNewLineWarning":false,"position":6,"left":898,"right":898},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":899,"text":" This allows the query plan for the \u003ccommand\u003eSELECT\u003c/command\u003e to","html":" This allows the query plan for the \u0026lt;command\u0026gt;SELECT\u0026lt;/command\u0026gt; to","displayNoNewLineWarning":false,"position":7,"left":899,"right":899},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":900,"text":" be prepared just once and then reused for subsequent","html":" be prepared just once and then reused for subsequent","displayNoNewLineWarning":false,"position":8,"left":900,"right":900},{"stylingDirective":null,"type":"HUNK","blobLineNumber":945,"text":"@@ -946,8 +946,7 @@ IF count(*) \u0026gt; 0 FROM my_table THEN ...","html":"@@ -946,8 +946,7 @@ IF count(*) \u0026amp;gt; 0 FROM my_table THEN ...","displayNoNewLineWarning":false,"position":9,"left":945,"right":945},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":946,"text":" \u003capplication\u003ePL/pgSQL\u003c/application\u003e.","html":" \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt;.","displayNoNewLineWarning":false,"position":10,"left":946,"right":946},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":947,"text":" Anything not recognized as one of these statement types is presumed","html":" Anything not recognized as one of these statement types is presumed","displayNoNewLineWarning":false,"position":11,"left":947,"right":947},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":948,"text":" to be an SQL command and is sent to the main database engine to execute,","html":" to be an SQL command and is sent to the main database engine to execute,","displayNoNewLineWarning":false,"position":12,"left":948,"right":948},{"stylingDirective":null,"type":"DELETION","blobLineNumber":949,"text":"- as described in \u003cxref linkend=\"plpgsql-statements-sql-noresult\"/\u003e","html":"- as described in \u0026lt;xref linkend=\u0026quot;plpgsql-statements-sql-noresult\u0026quot;/\u0026gt;","displayNoNewLineWarning":false,"position":13,"left":949,"right":948},{"stylingDirective":null,"type":"DELETION","blobLineNumber":950,"text":"- and \u003cxref linkend=\"plpgsql-statements-sql-onerow\"/\u003e.","html":"- and \u0026lt;xref linkend=\u0026quot;plpgsql-statements-sql-onerow\u0026quot;/\u0026gt;.","displayNoNewLineWarning":false,"position":14,"left":950,"right":948},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":949,"text":"+ as described in \u003cxref linkend=\"plpgsql-statements-general-sql\"/\u003e.","html":"+ as described in \u0026lt;xref linkend=\u0026quot;plpgsql-statements-general-sql\u0026quot;/\u0026gt;.","displayNoNewLineWarning":false,"position":15,"left":950,"right":949},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":950,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":16,"left":951,"right":950},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":951,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":17,"left":952,"right":951},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":952,"text":" \u003csect2 id=\"plpgsql-statements-assignment\"\u003e","html":" \u0026lt;sect2 id=\u0026quot;plpgsql-statements-assignment\u0026quot;\u0026gt;","displayNoNewLineWarning":false,"position":18,"left":953,"right":952},{"stylingDirective":null,"type":"HUNK","blobLineNumber":991,"text":"@@ -993,31 +992,78 @@ complex_array[n].realpart = 12.3;","html":"@@ -993,31 +992,78 @@ complex_array[n].realpart = 12.3;","displayNoNewLineWarning":false,"position":19,"left":992,"right":991},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":992,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":20,"left":993,"right":992},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":993,"text":" \u003c/sect2\u003e","html":" \u0026lt;/sect2\u0026gt;","displayNoNewLineWarning":false,"position":21,"left":994,"right":993},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":994,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":22,"left":995,"right":994},{"stylingDirective":null,"type":"DELETION","blobLineNumber":996,"text":"- \u003csect2 id=\"plpgsql-statements-sql-noresult\"\u003e","html":"- \u0026lt;sect2 id=\u0026quot;plpgsql-statements-\u003cspan class=\"x x-first x-last\"\u003esql-noresult\u003c/span\u003e\u0026quot;\u0026gt;","displayNoNewLineWarning":false,"position":23,"left":996,"right":994},{"stylingDirective":null,"type":"DELETION","blobLineNumber":997,"text":"- \u003ctitle\u003eExecuting a Command with No Result\u003c/title\u003e","html":"- \u0026lt;title\u0026gt;Executing \u003cspan class=\"x x-first x-last\"\u003ea Command with No Result\u003c/span\u003e\u0026lt;/title\u0026gt;","displayNoNewLineWarning":false,"position":24,"left":997,"right":994},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":995,"text":"+ \u003csect2 id=\"plpgsql-statements-general-sql\"\u003e","html":"+ \u0026lt;sect2 id=\u0026quot;plpgsql-statements-\u003cspan class=\"x x-first x-last\"\u003egeneral-sql\u003c/span\u003e\u0026quot;\u0026gt;","displayNoNewLineWarning":false,"position":25,"left":997,"right":995},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":996,"text":"+ \u003ctitle\u003eExecuting SQL Commands\u003c/title\u003e","html":"+ \u0026lt;title\u0026gt;Executing \u003cspan class=\"x x-first x-last\"\u003eSQL Commands\u003c/span\u003e\u0026lt;/title\u0026gt;","displayNoNewLineWarning":false,"position":26,"left":997,"right":996},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":997,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":27,"left":998,"right":997},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":998,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":28,"left":999,"right":998},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1000,"text":"- For any SQL command that does not return rows, for example","html":"- For any SQL command that does not return rows, for example","displayNoNewLineWarning":false,"position":29,"left":1000,"right":998},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1001,"text":"- \u003ccommand\u003eINSERT\u003c/command\u003e without a \u003cliteral\u003eRETURNING\u003c/literal\u003e clause, you can","html":"- \u0026lt;command\u0026gt;INSERT\u0026lt;/command\u0026gt; without a \u0026lt;literal\u0026gt;RETURNING\u0026lt;/literal\u0026gt; clause, you can","displayNoNewLineWarning":false,"position":30,"left":1001,"right":998},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1002,"text":"- execute the command within a \u003capplication\u003ePL/pgSQL\u003c/application\u003e function","html":"- execute the command within a \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; function","displayNoNewLineWarning":false,"position":31,"left":1002,"right":998},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1003,"text":"- just by writing the command.","html":"- just by writing the command.","displayNoNewLineWarning":false,"position":32,"left":1003,"right":998},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":999,"text":"+ In general, any SQL command that does not return rows can be executed","html":"+ In general, any SQL command that does not return rows can be executed","displayNoNewLineWarning":false,"position":33,"left":1003,"right":999},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1000,"text":"+ within a \u003capplication\u003ePL/pgSQL\u003c/application\u003e function just by writing","html":"+ within a \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; function just by writing","displayNoNewLineWarning":false,"position":34,"left":1003,"right":1000},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1001,"text":"+ the command. For example, you could create and fill a table by writing","html":"+ the command. For example, you could create and fill a table by writing","displayNoNewLineWarning":false,"position":35,"left":1003,"right":1001},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1002,"text":"+\u003cprogramlisting\u003e","html":"+\u0026lt;programlisting\u0026gt;","displayNoNewLineWarning":false,"position":36,"left":1003,"right":1002},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1003,"text":"+CREATE TABLE mytable (id int primary key, data text);","html":"+CREATE TABLE mytable (id int primary key, data text);","displayNoNewLineWarning":false,"position":37,"left":1003,"right":1003},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1004,"text":"+INSERT INTO mytable VALUES (1,'one'), (2,'two');","html":"+INSERT INTO mytable VALUES (1,\u0026#39;one\u0026#39;), (2,\u0026#39;two\u0026#39;);","displayNoNewLineWarning":false,"position":38,"left":1003,"right":1004},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1005,"text":"+\u003c/programlisting\u003e","html":"+\u0026lt;/programlisting\u0026gt;","displayNoNewLineWarning":false,"position":39,"left":1003,"right":1005},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1006,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":40,"left":1004,"right":1006},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1007,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":41,"left":1005,"right":1007},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1008,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":42,"left":1006,"right":1008},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1007,"text":"- Any \u003capplication\u003ePL/pgSQL\u003c/application\u003e variable name appearing","html":"- Any \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; variable name appearing","displayNoNewLineWarning":false,"position":43,"left":1007,"right":1008},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1008,"text":"- in the command text is treated as a parameter, and then the","html":"- in the command text is treated as a parameter, and then the","displayNoNewLineWarning":false,"position":44,"left":1008,"right":1008},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1009,"text":"+ If the command does return rows (for example \u003ccommand\u003eSELECT\u003c/command\u003e,","html":"+ If the command does return rows (for example \u0026lt;command\u0026gt;SELECT\u0026lt;/command\u0026gt;,","displayNoNewLineWarning":false,"position":45,"left":1008,"right":1009},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1010,"text":"+ or \u003ccommand\u003eINSERT\u003c/command\u003e/\u003ccommand\u003eUPDATE\u003c/command\u003e/\u003ccommand\u003eDELETE\u003c/command\u003e","html":"+ or \u0026lt;command\u0026gt;INSERT\u0026lt;/command\u0026gt;/\u0026lt;command\u0026gt;UPDATE\u0026lt;/command\u0026gt;/\u0026lt;command\u0026gt;DELETE\u0026lt;/command\u0026gt;","displayNoNewLineWarning":false,"position":46,"left":1008,"right":1010},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1011,"text":"+ with \u003cliteral\u003eRETURNING\u003c/literal\u003e), there are two ways to proceed.","html":"+ with \u0026lt;literal\u0026gt;RETURNING\u0026lt;/literal\u0026gt;), there are two ways to proceed.","displayNoNewLineWarning":false,"position":47,"left":1008,"right":1011},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1012,"text":"+ When the command will return at most one row, or you only care about","html":"+ When the command will return at most one row, or you only care about","displayNoNewLineWarning":false,"position":48,"left":1008,"right":1012},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1013,"text":"+ the first row of output, write the command as usual but add","html":"+ the first row of output, write the command as usual but add","displayNoNewLineWarning":false,"position":49,"left":1008,"right":1013},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1014,"text":"+ an \u003cliteral\u003eINTO\u003c/literal\u003e clause to capture the output, as described","html":"+ an \u0026lt;literal\u0026gt;INTO\u0026lt;/literal\u0026gt; clause to capture the output, as described","displayNoNewLineWarning":false,"position":50,"left":1008,"right":1014},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1015,"text":"+ in \u003cxref linkend=\"plpgsql-statements-sql-onerow\"/\u003e.","html":"+ in \u0026lt;xref linkend=\u0026quot;plpgsql-statements-sql-onerow\u0026quot;/\u0026gt;.","displayNoNewLineWarning":false,"position":51,"left":1008,"right":1015},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1016,"text":"+ To process all of the output rows, write the command as the data","html":"+ To process all of the output rows, write the command as the data","displayNoNewLineWarning":false,"position":52,"left":1008,"right":1016},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1017,"text":"+ source for a \u003ccommand\u003eFOR\u003c/command\u003e loop, as described in","html":"+ source for a \u0026lt;command\u0026gt;FOR\u0026lt;/command\u0026gt; loop, as described in","displayNoNewLineWarning":false,"position":53,"left":1008,"right":1017},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1018,"text":"+ \u003cxref linkend=\"plpgsql-records-iterating\"/\u003e.","html":"+ \u0026lt;xref linkend=\u0026quot;plpgsql-records-iterating\u0026quot;/\u0026gt;.","displayNoNewLineWarning":false,"position":54,"left":1008,"right":1018},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1019,"text":"+ \u003c/para\u003e","html":"+ \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":55,"left":1008,"right":1019},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1020,"text":"+","html":"+","displayNoNewLineWarning":false,"position":56,"left":1008,"right":1020},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1021,"text":"+ \u003cpara\u003e","html":"+ \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":57,"left":1008,"right":1021},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1022,"text":"+ Usually it is not sufficient just to execute statically-defined SQL","html":"+ Usually it is not sufficient just to execute statically-defined SQL","displayNoNewLineWarning":false,"position":58,"left":1008,"right":1022},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1023,"text":"+ commands. Typically you'll want a command to use varying data values,","html":"+ commands. Typically you\u0026#39;ll want a command to use varying data values,","displayNoNewLineWarning":false,"position":59,"left":1008,"right":1023},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1024,"text":"+ or even to vary in more fundamental ways such as by using different","html":"+ or even to vary in more fundamental ways such as by using different","displayNoNewLineWarning":false,"position":60,"left":1008,"right":1024},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1025,"text":"+ table names at different times. Again, there are two ways to proceed","html":"+ table names at different times. Again, there are two ways to proceed","displayNoNewLineWarning":false,"position":61,"left":1008,"right":1025},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1026,"text":"+ depending on the situation.","html":"+ depending on the situation.","displayNoNewLineWarning":false,"position":62,"left":1008,"right":1026},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1027,"text":"+ \u003c/para\u003e","html":"+ \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":63,"left":1008,"right":1027},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1028,"text":"+","html":"+","displayNoNewLineWarning":false,"position":64,"left":1008,"right":1028},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1029,"text":"+ \u003cpara\u003e","html":"+ \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":65,"left":1008,"right":1029},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1030,"text":"+ \u003capplication\u003ePL/pgSQL\u003c/application\u003e variable values can be","html":"+ \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; variable values can be","displayNoNewLineWarning":false,"position":66,"left":1008,"right":1030},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1031,"text":"+ automatically inserted into optimizable SQL commands, which","html":"+ automatically inserted into optimizable SQL commands, which","displayNoNewLineWarning":false,"position":67,"left":1008,"right":1031},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1032,"text":"+ are \u003ccommand\u003eSELECT\u003c/command\u003e, \u003ccommand\u003eINSERT\u003c/command\u003e,","html":"+ are \u0026lt;command\u0026gt;SELECT\u0026lt;/command\u0026gt;, \u0026lt;command\u0026gt;INSERT\u0026lt;/command\u0026gt;,","displayNoNewLineWarning":false,"position":68,"left":1008,"right":1032},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1033,"text":"+ \u003ccommand\u003eUPDATE\u003c/command\u003e, \u003ccommand\u003eDELETE\u003c/command\u003e, and certain","html":"+ \u0026lt;command\u0026gt;UPDATE\u0026lt;/command\u0026gt;, \u0026lt;command\u0026gt;DELETE\u0026lt;/command\u0026gt;, and certain","displayNoNewLineWarning":false,"position":69,"left":1008,"right":1033},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1034,"text":"+ utility commands that incorporate one of these, such","html":"+ utility commands that incorporate one of these, such","displayNoNewLineWarning":false,"position":70,"left":1008,"right":1034},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1035,"text":"+ as \u003ccommand\u003eEXPLAIN\u003c/command\u003e and \u003ccommand\u003eCREATE TABLE ... AS","html":"+ as \u0026lt;command\u0026gt;EXPLAIN\u0026lt;/command\u0026gt; and \u0026lt;command\u0026gt;CREATE TABLE ... AS","displayNoNewLineWarning":false,"position":71,"left":1008,"right":1035},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1036,"text":"+ SELECT\u003c/command\u003e. In these commands,","html":"+ SELECT\u0026lt;/command\u0026gt;. In these commands,","displayNoNewLineWarning":false,"position":72,"left":1008,"right":1036},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1037,"text":"+ any \u003capplication\u003ePL/pgSQL\u003c/application\u003e variable name appearing","html":"+ any \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; variable name appearing","displayNoNewLineWarning":false,"position":73,"left":1008,"right":1037},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1038,"text":"+ in the command text is replaced by a query parameter, and then the","html":"+ in the command text is replaced by a query parameter, and then the","displayNoNewLineWarning":false,"position":74,"left":1008,"right":1038},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1039,"text":" current value of the variable is provided as the parameter value","html":" current value of the variable is provided as the parameter value","displayNoNewLineWarning":false,"position":75,"left":1009,"right":1039},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1040,"text":" at run time. This is exactly like the processing described earlier","html":" at run time. This is exactly like the processing described earlier","displayNoNewLineWarning":false,"position":76,"left":1010,"right":1040},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1041,"text":" for expressions; for details see \u003cxref linkend=\"plpgsql-var-subst\"/\u003e.","html":" for expressions; for details see \u0026lt;xref linkend=\u0026quot;plpgsql-var-subst\u0026quot;/\u0026gt;.","displayNoNewLineWarning":false,"position":77,"left":1011,"right":1041},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1042,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":78,"left":1012,"right":1042},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1043,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":79,"left":1013,"right":1043},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1044,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":80,"left":1014,"right":1044},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1015,"text":"- When executing a SQL command in this way,","html":"- When executing \u003cspan class=\"x x-first x-last\"\u003ea\u003c/span\u003e SQL command in this way,","displayNoNewLineWarning":false,"position":81,"left":1015,"right":1044},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1045,"text":"+ When executing an optimizable SQL command in this way,","html":"+ When executing \u003cspan class=\"x x-first x-last\"\u003ean optimizable\u003c/span\u003e SQL command in this way,","displayNoNewLineWarning":false,"position":82,"left":1015,"right":1045},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1046,"text":" \u003capplication\u003ePL/pgSQL\u003c/application\u003e may cache and re-use the execution","html":" \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; may cache and re-use the execution","displayNoNewLineWarning":false,"position":83,"left":1016,"right":1046},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1047,"text":" plan for the command, as discussed in","html":" plan for the command, as discussed in","displayNoNewLineWarning":false,"position":84,"left":1017,"right":1047},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1048,"text":" \u003cxref linkend=\"plpgsql-plan-caching\"/\u003e.","html":" \u0026lt;xref linkend=\u0026quot;plpgsql-plan-caching\u0026quot;/\u0026gt;.","displayNoNewLineWarning":false,"position":85,"left":1018,"right":1048},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1049,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":86,"left":1019,"right":1049},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1050,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":87,"left":1020,"right":1050},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1051,"text":"+ \u003cpara\u003e","html":"+ \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":88,"left":1020,"right":1051},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1052,"text":"+ Non-optimizable SQL commands (also called utility commands) are not","html":"+ Non-optimizable SQL commands (also called utility commands) are not","displayNoNewLineWarning":false,"position":89,"left":1020,"right":1052},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1053,"text":"+ capable of accepting query parameters. So automatic substitution","html":"+ capable of accepting query parameters. So automatic substitution","displayNoNewLineWarning":false,"position":90,"left":1020,"right":1053},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1054,"text":"+ of \u003capplication\u003ePL/pgSQL\u003c/application\u003e variables does not work in such","html":"+ of \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; variables does not work in such","displayNoNewLineWarning":false,"position":91,"left":1020,"right":1054},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1055,"text":"+ commands. To include non-constant text in a utility command executed","html":"+ commands. To include non-constant text in a utility command executed","displayNoNewLineWarning":false,"position":92,"left":1020,"right":1055},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1056,"text":"+ from \u003capplication\u003ePL/pgSQL\u003c/application\u003e, you must build the utility","html":"+ from \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt;, you must build the utility","displayNoNewLineWarning":false,"position":93,"left":1020,"right":1056},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1057,"text":"+ command as a string and then \u003ccommand\u003eEXECUTE\u003c/command\u003e it, as","html":"+ command as a string and then \u0026lt;command\u0026gt;EXECUTE\u0026lt;/command\u0026gt; it, as","displayNoNewLineWarning":false,"position":94,"left":1020,"right":1057},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1058,"text":"+ discussed in \u003cxref linkend=\"plpgsql-statements-executing-dyn\"/\u003e.","html":"+ discussed in \u0026lt;xref linkend=\u0026quot;plpgsql-statements-executing-dyn\u0026quot;/\u0026gt;.","displayNoNewLineWarning":false,"position":95,"left":1020,"right":1058},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1059,"text":"+ \u003c/para\u003e","html":"+ \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":96,"left":1020,"right":1059},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1060,"text":"+","html":"+","displayNoNewLineWarning":false,"position":97,"left":1020,"right":1060},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1061,"text":"+ \u003cpara\u003e","html":"+ \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":98,"left":1020,"right":1061},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1062,"text":"+ \u003ccommand\u003eEXECUTE\u003c/command\u003e must also be used if you want to modify","html":"+ \u0026lt;command\u0026gt;EXECUTE\u0026lt;/command\u0026gt; must also be used if you want to modify","displayNoNewLineWarning":false,"position":99,"left":1020,"right":1062},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1063,"text":"+ the command in some other way than supplying a data value, for example","html":"+ the command in some other way than supplying a data value, for example","displayNoNewLineWarning":false,"position":100,"left":1020,"right":1063},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1064,"text":"+ by changing a table name.","html":"+ by changing a table name.","displayNoNewLineWarning":false,"position":101,"left":1020,"right":1064},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1065,"text":"+ \u003c/para\u003e","html":"+ \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":102,"left":1020,"right":1065},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1066,"text":"+","html":"+","displayNoNewLineWarning":false,"position":103,"left":1020,"right":1066},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1067,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":104,"left":1021,"right":1067},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1068,"text":" Sometimes it is useful to evaluate an expression or \u003ccommand\u003eSELECT\u003c/command\u003e","html":" Sometimes it is useful to evaluate an expression or \u0026lt;command\u0026gt;SELECT\u0026lt;/command\u0026gt;","displayNoNewLineWarning":false,"position":105,"left":1022,"right":1068},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1069,"text":" query but discard the result, for example when calling a function","html":" query but discard the result, for example when calling a function","displayNoNewLineWarning":false,"position":106,"left":1023,"righ 8000 t":1069},{"stylingDirective":null,"type":"HUNK","blobLineNumber":1082,"text":"@@ -1037,7 +1083,7 @@ PERFORM \u003creplaceable\u003equery\u003c/replaceable\u003e;","html":"@@ -1037,7 +1083,7 @@ PERFORM \u0026lt;replaceable\u0026gt;query\u0026lt;/replaceable\u0026gt;;","displayNoNewLineWarning":false,"position":107,"left":1036,"right":1082},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1083,"text":" place the query in parentheses. (In this case, the query can only","html":" place the query in parentheses. (In this case, the query can only","displayNoNewLineWarning":false,"position":108,"left":1037,"right":1083},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1084,"text":" return one row.)","html":" return one row.)","displayNoNewLineWarning":false,"position":109,"left":1038,"right":1084},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1085,"text":" \u003capplication\u003ePL/pgSQL\u003c/application\u003e variables will be","html":" \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; variables will be","displayNoNewLineWarning":false,"position":110,"left":1039,"right":1085},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1040,"text":"- substituted into the query just as for commands that return no result,","html":"- substituted into the query just as \u003cspan class=\"x x-first x-last\"\u003efor commands that return no result\u003c/span\u003e,","displayNoNewLineWarning":false,"position":111,"left":1040,"right":1085},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1086,"text":"+ substituted into the query just as described above,","html":"+ substituted into the query just as \u003cspan class=\"x x-first x-last\"\u003edescribed above\u003c/span\u003e,","displayNoNewLineWarning":false,"position":112,"left":1040,"right":1086},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1087,"text":" and the plan is cached in the same way. Also, the special variable","html":" and the plan is cached in the same way. Also, the special variable","displayNoNewLineWarning":false,"position":113,"left":1041,"right":1087},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1088,"text":" \u003cliteral\u003eFOUND\u003c/literal\u003e is set to true if the query produced at","html":" \u0026lt;literal\u0026gt;FOUND\u0026lt;/literal\u0026gt; is set to true if the query produced at","displayNoNewLineWarning":false,"position":114,"left":1042,"right":1088},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1089,"text":" least one row, or false if it produced no rows (see","html":" least one row, or false if it produced no rows (see","displayNoNewLineWarning":false,"position":115,"left":1043,"right":1089},{"stylingDirective":null,"type":"HUNK","blobLineNumber":1110,"text":"@@ -1065,7 +1111,7 @@ PERFORM create_mv('cs_session_page_requests_mv', my_query);","html":"@@ -1065,7 +1111,7 @@ PERFORM create_mv(\u0026#39;cs_session_page_requests_mv\u0026#39;, my_query);","displayNoNewLineWarning":false,"position":116,"left":1064,"right":1110},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1111,"text":" \u003c/sect2\u003e","html":" \u0026lt;/sect2\u0026gt;","displayNoNewLineWarning":false,"position":117,"left":1065,"right":1111},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1112,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":118,"left":1066,"right":1112},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1113,"text":" \u003csect2 id=\"plpgsql-statements-sql-onerow\"\u003e","html":" \u0026lt;sect2 id=\u0026quot;plpgsql-statements-sql-onerow\u0026quot;\u0026gt;","displayNoNewLineWarning":false,"position":119,"left":1067,"right":1113},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1068,"text":"- \u003ctitle\u003eExecuting a Query with a Single-Row Result\u003c/title\u003e","html":"- \u0026lt;title\u0026gt;Executing a \u003cspan class=\"x x-first x-last\"\u003eQuery\u003c/span\u003e with a Single-Row Result\u0026lt;/title\u0026gt;","displayNoNewLineWarning":false,"position":120,"left":1068,"right":1113},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1114,"text":"+ \u003ctitle\u003eExecuting a Command with a Single-Row Result\u003c/title\u003e","html":"+ \u0026lt;title\u0026gt;Executing a \u003cspan class=\"x x-first x-last\"\u003eCommand\u003c/span\u003e with a Single-Row Result\u0026lt;/title\u0026gt;","displayNoNewLineWarning":false,"position":121,"left":1068,"right":1114},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1115,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":122,"left":1069,"right":1115},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1116,"text":" \u003cindexterm zone=\"plpgsql-statements-sql-onerow\"\u003e","html":" \u0026lt;indexterm zone=\u0026quot;plpgsql-statements-sql-onerow\u0026quot;\u0026gt;","displayNoNewLineWarning":false,"position":123,"left":1070,"right":1116},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1117,"text":" \u003cprimary\u003eSELECT INTO\u003c/primary\u003e","html":" \u0026lt;primary\u0026gt;SELECT INTO\u0026lt;/primary\u0026gt;","displayNoNewLineWarning":false,"position":124,"left":1071,"right":1117},{"stylingDirective":null,"type":"HUNK","blobLineNumber":1139,"text":"@@ -1094,12 +1140,13 @@ DELETE ... RETURNING \u003creplaceable\u003eexpressions\u003c/replaceable\u003e INTO \u003coptional\u003eSTRIC","html":"@@ -1094,12 +1140,13 @@ DELETE ... RETURNING \u0026lt;replaceable\u0026gt;expressions\u0026lt;/replaceable\u0026gt; INTO \u0026lt;optional\u0026gt;STRIC","displayNoNewLineWarning":false,"position":125,"left":1093,"right":1139},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1140,"text":" variable, or a comma-separated list of simple variables and","html":" variable, or a comma-separated list of simple variables and","displayNoNewLineWarning":false,"position":126,"left":1094,"right":1140},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1141,"text":" record/row fields.","html":" record/row fields.","displayNoNewLineWarning":false,"position":127,"left":1095,"right":1141},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1142,"text":" \u003capplication\u003ePL/pgSQL\u003c/application\u003e variables will be","html":" \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; variables will be","displayNoNewLineWarning":false,"position":128,"left":1096,"right":1142},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1097,"text":"- substituted into the rest of the query, and the plan is cached,","html":"- substituted into the rest of the query, and the plan is cached,","displayNoNewLineWarning":false,"position":129,"left":1097,"right":1142},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1098,"text":"- just as described above for commands that do not return rows.","html":"- just as described above for commands that do not return rows.","displayNoNewLineWarning":false,"position":130,"left":1098,"right":1142},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1143,"text":"+ substituted into the rest of the command (that is, everything but the","html":"+ substituted into the rest of the command (that is, everything but the","displayNoNewLineWarning":false,"position":131,"left":1098,"right":1143},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1144,"text":"+ \u003cliteral\u003eINTO\u003c/literal\u003e clause) just as described above,","html":"+ \u0026lt;literal\u0026gt;INTO\u0026lt;/literal\u0026gt; clause) just as described above,","displayNoNewLineWarning":false,"position":132,"left":1098,"right":1144},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1145,"text":"+ and the plan is cached in the same way.","html":"+ and the plan is cached in the same way.","displayNoNewLineWarning":false,"position":133,"left":1098,"right":1145},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1146,"text":" This works for \u003ccommand\u003eSELECT\u003c/command\u003e,","html":" This works for \u0026lt;command\u0026gt;SELECT\u0026lt;/command\u0026gt;,","displayNoNewLineWarning":false,"position":134,"left":1099,"right":1146},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1147,"text":" \u003ccommand\u003eINSERT\u003c/command\u003e/\u003ccommand\u003eUPDATE\u003c/command\u003e/\u003ccommand\u003eDELETE\u003c/command\u003e with","html":" \u0026lt;command\u0026gt;INSERT\u0026lt;/command\u0026gt;/\u0026lt;command\u0026gt;UPDATE\u0026lt;/command\u0026gt;/\u0026lt;command\u0026gt;DELETE\u0026lt;/command\u0026gt; with","displayNoNewLineWarning":false,"position":135,"left":1100,"right":1147},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1101,"text":"- \u003cliteral\u003eRETURNING\u003c/literal\u003e, and utility commands that return row-set","html":"- \u0026lt;literal\u0026gt;RETURNING\u0026lt;/literal\u0026gt;, and utility commands\u003cspan class=\"x x-first x-last\"\u003e that return row-set\u003c/span\u003e","displayNoNewLineWarning":false,"position":136,"left":1101,"right":1147},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1102,"text":"- results (such as \u003ccommand\u003eEXPLAIN\u003c/command\u003e).","html":"- \u003cspan class=\"x x-first x-last\"\u003eresults (\u003c/span\u003esuch as \u0026lt;command\u0026gt;EXPLAIN\u0026lt;/command\u0026gt;\u003cspan class=\"x x-first x-last\"\u003e)\u003c/span\u003e.","displayNoNewLineWarning":false,"position":137,"left":1102,"right":1147},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1148,"text":"+ \u003cliteral\u003eRETURNING\u003c/literal\u003e, and certain utility commands","html":"+ \u0026lt;literal\u0026gt;RETURNING\u0026lt;/literal\u0026gt;, and \u003cspan class=\"x x-first x-last\"\u003ecertain \u003c/span\u003eutility commands","displayNoNewLineWarning":false,"position":138,"left":1102,"right":1148},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1149,"text":"+ that return row sets, such as \u003ccommand\u003eEXPLAIN\u003c/command\u003e.","html":"+ \u003cspan class=\"x x-first x-last\"\u003ethat return row sets, \u003c/span\u003esuch as \u0026lt;command\u0026gt;EXPLAIN\u0026lt;/command\u0026gt;.","displayNoNewLineWarning":false,"position":139,"left":1102,"right":1149},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1150,"text":" Except for the \u003cliteral\u003eINTO\u003c/literal\u003e clause, the SQL command is the same","html":" Except for the \u0026lt;literal\u0026gt;INTO\u0026lt;/literal\u0026gt; clause, the SQL command is the same","displayNoNewLineWarning":false,"position":140,"left":1103,"right":1150},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1151,"text":" as it would be written outside \u003capplication\u003ePL/pgSQL\u003c/application\u003e.","html":" as it would be written outside \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt;.","displayNoNewLineWarning":false,"position":141,"left":1104,"right":1151},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1152,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":142,"left":1105,"right":1152},{"stylingDirective":null,"type":"HUNK","blobLineNumber":1163,"text":"@@ -1117,11 +1164,12 @@ DELETE ... RETURNING \u003creplaceable\u003eexpressions\u003c/replaceable\u003e INTO \u003coptional\u003eSTRIC","html":"@@ -1117,11 +1164,12 @@ DELETE ... RETURNING \u0026lt;replaceable\u0026gt;expressions\u0026lt;/replaceable\u0026gt; INTO \u0026lt;optional\u0026gt;STRIC","displayNoNewLineWarning":false,"position":143,"left":1116,"right":1163},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1164,"text":" \u003c/tip\u003e","html":" \u0026lt;/tip\u0026gt;","displayNoNewLineWarning":false,"position":144,"left":1117,"right":1164},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1165,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":145,"left":1118,"right":1165},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1166,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":146,"left":1119,"right":1166},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1120,"text":"- If a row or a variable list is used as target, the query's result columns","html":"- If a row or a variable list is used as target, the query\u0026#39;s result columns","displayNoNewLineWarning":false,"position":147,"left":1120,"right":1166},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1167,"text":"+ If a row variable or a variable list is used as target,","html":"+ If a row variable or a variable list is used as target,","displayNoNewLineWarning":false,"position":148,"left":1120,"right":1167},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1168,"text":"+ the command's result columns","html":"+ the command\u0026#39;s result columns","displayNoNewLineWarning":false,"position":149,"left":1120,"right":1168},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1169,"text":" must exactly match the structure of the target as to number and data","html":" must exactly match the structure of the target as to number and data","displayNoNewLineWarning":false,"position":150,"left":1121,"right":1169},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1170,"text":" types, or else a run-time error","html":" types, or else a run-time error","displayNoNewLineWarning":false,"position":151,"left":1122,"right":1170},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1171,"text":" occurs. When a record variable is the target, it automatically","html":" occurs. When a record variable is the target, it automatically","displayNoNewLineWarning":false,"position":152,"left":1123,"right":1171},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1124,"text":"- configures itself to the row type of the query result columns.","html":"- configures itself to the row type of the \u003cspan class=\"x x-first x-last\"\u003equery\u003c/span\u003e result columns.","displayNoNewLineWarning":false,"position":153,"left":1124,"right":1171},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1172,"text":"+ configures itself to the row type of the command's result columns.","html":"+ configures itself to the row type of the \u003cspan class=\"x x-first x-last\"\u003ecommand\u0026#39;s\u003c/span\u003e result columns.","displayNoNewLineWarning":false,"position":154,"left":1124,"right":1172},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1173,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":155,"left":1125,"right":1173},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1174,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":156,"left":1126,"right":1174},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1175,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":157,"left":1127,"right":1175},{"stylingDirective":null,"type":"HUNK","blobLineNumber":1184,"text":"@@ -1137,7 +1185,7 @@ DELETE ... RETURNING \u003creplaceable\u003eexpressions\u003c/replaceable\u003e INTO \u003coptional\u003eSTRIC","html":"@@ -1137,7 +1185,7 @@ DELETE ... RETURNING \u0026lt;replaceable\u0026gt;expressions\u0026lt;/replaceable\u0026gt; INTO \u0026lt;optional\u0026gt;STRIC","displayNoNewLineWarning":false,"position":158,"left":1136,"right":1184},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1185,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":159,"left":1137,"right":1185},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1186,"text":" If \u003cliteral\u003eSTRICT\u003c/literal\u003e is not specified in the \u003cliteral\u003eINTO\u003c/literal\u003e","html":" If \u0026lt;literal\u0026gt;STRICT\u0026lt;/literal\u0026gt; is not specified in the \u0026lt;literal\u0026gt;INTO\u0026lt;/literal\u0026gt;","displayNoNewLineWarning":false,"position":160,"left":1138,"right":1186},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1187,"text":" clause, then \u003creplaceable\u003etarget\u003c/replaceable\u003e will be set to the first","html":" clause, then \u0026lt;replaceable\u0026gt;target\u0026lt;/replaceable\u0026gt; will be set to the first","displayNoNewLineWarning":false,"position":161,"left":1139,"right":1187},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1140,"text":"- row returned by the query, or to nulls if the query returned no rows.","html":"- row returned by the \u003cspan class=\"x x-first x-last\"\u003equery\u003c/span\u003e, or to nulls if the \u003cspan class=\"x x-first x-last\"\u003equery\u003c/span\u003e returned no rows.","displayNoNewLineWarning":false,"position":162,"left":1140,"right":1187},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1188,"text":"+ row returned by the command, or to nulls if the command returned no rows.","html":"+ row returned by the \u003cspan class=\"x x-first x-last\"\u003ecommand\u003c/span\u003e, or to nulls if the \u003cspan class=\"x x-first x-last\"\u003ecommand\u003c/span\u003e returned no rows.","displayNoNewLineWarning":false,"position":163,"left":1140,"right":1188},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1189,"text":" (Note that \u003cquote\u003ethe first row\u003c/quote\u003e is not","html":" (Note that \u0026lt;quote\u0026gt;the first row\u0026lt;/quote\u0026gt; is not","displayNoNewLineWarning":false,"position":164,"left":1141,"right":1189},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1190,"text":" well-defined unless you've used \u003cliteral\u003eORDER BY\u003c/literal\u003e.) Any result rows","html":" well-defined unless you\u0026#39;ve used \u0026lt;literal\u0026gt;ORDER BY\u0026lt;/literal\u0026gt;.) Any result rows","displayNoNewLineWarning":false,"position":165,"left":1142,"right":1190},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1191,"text":" after the first row are discarded.","html":" after the first row are discarded.","displayNoNewLineWarning":false,"position":166,"left":1143,"right":1191},{"stylingDirective":null,"type":"HUNK","blobLineNumber":1199,"text":"@@ -1152,7 +1200,7 @@ IF NOT FOUND THEN","html":"@@ -1152,7 +1200,7 @@ IF NOT FOUND THEN","displayNoNewLineWarning":false,"position":167,"left":1151,"right":1199},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1200,"text":" END IF;","html":" END IF;","displayNoNewLineWarning":false,"position":168,"left":1152,"right":1200},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1201,"text":" \u003c/programlisting\u003e","html":" \u0026lt;/programlisting\u0026gt;","displayNoNewLineWarning":false,"position":169,"left":1153,"right":1201},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1202,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":170,"left":1154,"right":1202},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1155,"text":"- If the \u003cliteral\u003eSTRICT\u003c/literal\u003e option is specified, the query must","html":"- If the \u0026lt;literal\u0026gt;STRICT\u0026lt;/literal\u0026gt; option is specified, the \u003cspan class=\"x x-first x-last\"\u003equery\u003c/span\u003e must","displayNoNewLineWarning":false,"position":171,"left":1155,"right":1202},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1203,"text":"+ If the \u003cliteral\u003eSTRICT\u003c/literal\u003e option is specified, the command must","html":"+ If the \u0026lt;literal\u0026gt;STRICT\u0026lt;/literal\u0026gt; option is specified, the \u003cspan class=\"x x-first x-last\"\u003ecommand\u003c/span\u003e must","displayNoNewLineWarning":false,"position":172,"left":1155,"right":1203},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1204,"text":" return exactly one row or a run-time error will be reported, either","html":" return exactly one row or a run-time error will be reported, either","displayNoNewLineWarning":false,"position":173,"left":1156,"right":1204},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1205,"text":" \u003cliteral\u003eNO_DATA_FOUND\u003c/literal\u003e (no rows) or \u003cliteral\u003eTOO_MANY_ROWS\u003c/literal\u003e","html":" \u0026lt;literal\u0026gt;NO_DATA_FOUND\u0026lt;/literal\u0026gt; (no rows) or \u0026lt;literal\u0026gt;TOO_MANY_ROWS\u0026lt;/literal\u0026gt;","displayNoNewLineWarning":false,"position":174,"left":1157,"right":1205},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1206,"text":" (more than one row). You can use an exception block if you wish","html":" (more than one row). You can use an exception block if you wish","displayNoNewLineWarning":false,"position":175,"left":1158,"right":1206},{"stylingDirective":null,"type":"HUNK","blobLineNumber":1233,"text":"@@ -1186,7 +1234,7 @@ END;","html":"@@ -1186,7 +1234,7 @@ END;","displayNoNewLineWarning":false,"position":176,"left":1185,"right":1233},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1234,"text":" then when an error is thrown because the requirements","html":" then when an error is thrown because the requirements","displayNoNewLineWarning":false,"position":177,"left":1186,"right":1234},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1235,"text":" of \u003cliteral\u003eSTRICT\u003c/literal\u003e are not met, the \u003cliteral\u003eDETAIL\u003c/literal\u003e part of","html":" of \u0026lt;literal\u0026gt;STRICT\u0026lt;/literal\u0026gt; are not met, the \u0026lt;literal\u0026gt;DETAIL\u0026lt;/literal\u0026gt; part of","displayNoNewLineWarning":false,"position":178,"left":1187,"right":1235},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1236,"text":" the error message will include information about the parameters","html":" the error message will include information about the parameters","displayNoNewLineWarning":false,"position":179,"left":1188,"right":1236},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1189,"text":"- passed to the query.","html":"- passed to the \u003cspan class=\"x x-first x-last\"\u003equery\u003c/span\u003e.","displayNoNewLineWarning":false,"position":180,"left":1189,"right":1236},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1237,"text":"+ passed to the command.","html":"+ passed to the \u003cspan class=\"x x-first x-last\"\u003ecommand\u003c/span\u003e.","displayNoNewLineWarning":false,"position":181,"left":1189,"right":1237},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1238,"text":" You can change the \u003cliteral\u003eprint_strict_params\u003c/literal\u003e","html":" You can change the \u0026lt;literal\u0026gt;print_strict_params\u0026lt;/literal\u0026gt;","displayNoNewLineWarning":false,"position":182,"left":1190,"right":1238},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1239,"text":" setting for all functions by setting","html":" setting for all functions by setting","displayNoNewLineWarning":false,"position":183,"left":1191,"right":1239},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1240,"text":" \u003cvarname\u003eplpgsql.print_strict_params\u003c/varname\u003e, though only subsequent","html":" \u0026lt;varname\u0026gt;plpgsql.print_strict_params\u0026lt;/varname\u0026gt;, though only subsequent","displayNoNewLineWarning":false,"position":184,"left":1192,"right":1240},{"stylingDirective":null,"type":"HUNK","blobLineNumber":1267,"text":"@@ -1220,11 +1268,6 @@ CONTEXT: PL/pgSQL function get_userid(text) line 6 at SQL statement","html":"@@ -1220,11 +1268,6 @@ CONTEXT: PL/pgSQL function get_userid(text) line 6 at SQL statement","displayNoNewLineWarning":false,"position":185,"left":1219,"right":1267},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1268,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":186,"left":1220,"right":1268},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1269,"text":" \u003c/note\u003e","html":" \u0026lt;/note\u0026gt;","displayNoNewLineWarning":false,"position":187,"left":1221,"right":1269},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1270,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":188,"left":1222,"right":1270},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1223,"text":"- \u003cpara\u003e","html":"- \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":189,"left":1223,"right":1270},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1224,"text":"- To handle cases where you need to process multiple result rows","html":"- To handle cases where you need to process multiple result rows","displayNoNewLineWarning":false,"position":190,"left":1224,"right":1270},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1225,"text":"- from a SQL query, see \u003cxref linkend=\"plpgsql-records-iterating\"/\u003e.","html":"- from a SQL query, see \u0026lt;xref linkend=\u0026quot;plpgsql-records-iterating\u0026quot;/\u0026gt;.","displayNoNewLineWarning":false,"position":191,"left":1225,"right":1270},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1226,"text":"- \u003c/para\u003e","html":"- \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":192,"left":1226,"right":1270},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1227,"text":"-","html":"-","displayNoNewLineWarning":false,"position":193,"left":1227,"right":1270},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1271,"text":" \u003c/sect2\u003e","html":" \u0026lt;/sect2\u0026gt;","displayNoNewLineWarning":false,"position":194,"left":1228,"right":1271},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1272,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":195,"left":1229,"right":1272},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1273,"text":" \u003csect2 id=\"plpgsql-statements-executing-dyn\"\u003e","html":" \u0026lt;sect2 id=\u0026quot;plpgsql-statements-executing-dyn\u0026quot;\u0026gt;","displayNoNewLineWarning":false,"position":196,"left":1230,"right":1273},{"stylingDirective":null,"type":"HUNK","blobLineNumber":1312,"text":"@@ -1270,20 +1313,20 @@ EXECUTE \u003creplaceable class=\"command\"\u003ecommand-string\u003c/replaceable\u003e \u003coptional\u003e INT","html":"@@ -1270,20 +1313,20 @@ EXECUTE \u0026lt;replaceable class=\u0026quot;command\u0026quot;\u0026gt;command-string\u0026lt;/replaceable\u0026gt; \u0026lt;optional\u0026gt; INT","displayNoNewLineWarning":false,"position":197,"left":1269,"right":1312},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1313,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":198,"left":1270,"right":1313},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1314,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":199,"left":1271,"right":1314},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1315,"text":" The \u003cliteral\u003eINTO\u003c/literal\u003e clause specifies where the results of","html":" The \u0026lt;literal\u0026gt;INTO\u0026lt;/literal\u0026gt; clause specifies where the results of","displayNoNewLineWarning":false,"position":200,"left":1272,"right":1315},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1273,"text":"- a SQL command returning rows should be assigned. If a row","html":"- a SQL command returning rows should be assigned. If a row","displayNoNewLineWarning":false,"position":201,"left":1273,"right":1315},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1316,"text":"+ a SQL command returning rows should be assigned. If a row variable","html":"+ a SQL command returning rows should be assigned. If a row\u003cspan class=\"x x-first x-last\"\u003e variable\u003c/span\u003e","displayNoNewLineWarning":false,"position":202,"left":1273,"right":1316},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1317,"text":" or variable list is provided, it must exactly match the structure","html":" or variable list is provided, it must exactly match the structure","displayNoNewLineWarning":false,"position":203,"left":1274,"right":1317},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1275,"text":"- of the query's results (when a","html":"- of the \u003cspan class=\"x x-first x-last\"\u003equery\u003c/span\u003e\u0026#39;s results\u003cspan class=\"x x-first x-last\"\u003e (when\u003c/span\u003e a","displayNoNewLineWarning":false,"position":204,"left":1275,"right":1317},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1276,"text":"- record variable is used, it will configure itself to match the","html":"- record variable is \u003cspan class=\"x x-first x-last\"\u003eused\u003c/span\u003e, it will configure itself to match the","displayNoNewLineWarning":false,"position":205,"left":1276,"right":1317},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1277,"text":"- result structure automatically). If multiple rows are returned,","html":"- result structure automatically\u003cspan class=\"x x-first x-last\"\u003e)\u003c/span\u003e. If multiple rows are returned,","displayNoNewLineWarning":false,"position":206,"left":1277,"right":1317},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1318,"text":"+ of the command's results; if a","html":"+ of the \u003cspan class=\"x x-first x-last\"\u003ecommand\u003c/span\u003e\u0026#39;s results\u003cspan class=\"x x-first x-last\"\u003e; if\u003c/span\u003e a","displayNoNewLineWarning":false,"position":207,"left":1277,"right":1318},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1319,"text":"+ record variable is provided, it will configure itself to match the","html":"+ record variable is \u003cspan class=\"x x-first x-last\"\u003eprovided\u003c/span\u003e, it will configure itself to match the","displayNoNewLineWarning":false,"position":208,"left":1277,"right":1319},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1320,"text":"+ result structure automatically. If multiple rows are returned,","html":"+ result structure automatically. If multiple rows are returned,","displayNoNewLineWarning":false,"position":209,"left":1277,"right":1320},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1321,"text":" only the first will be assigned to the \u003cliteral\u003eINTO\u003c/literal\u003e","html":" only the first will be assigned to the \u0026lt;literal\u0026gt;INTO\u0026lt;/literal\u0026gt;","displayNoNewLineWarning":false,"position":210,"left":1278,"right":1321},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1279,"text":"- variable. If no rows are returned, NULL is assigned to the","html":"- variable. If no rows are returned, NULL is assigned to the","displayNoNewLineWarning":false,"position":211,"left":1279,"right":1321},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1322,"text":"+ variable(s). If no rows are returned, NULL is assigned to the","html":"+ variable\u003cspan class=\"x x-first x-last\"\u003e(s)\u003c/span\u003e. If no rows are returned, NULL is assigned to the","displayNoNewLineWarning":false,"position":212,"left":1279,"right":1322},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1323,"text":" \u003cliteral\u003eINTO\u003c/literal\u003e variable(s). If no \u003cliteral\u003eINTO\u003c/literal\u003e","html":" \u0026lt;literal\u0026gt;INTO\u0026lt;/literal\u0026gt; variable(s). If no \u0026lt;literal\u0026gt;INTO\u0026lt;/literal\u0026gt;","displayNoNewLineWarning":false,"position":213,"left":1280,"right":1323},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1281,"text":"- clause is specified, the query results are discarded.","html":"- clause is specified, the \u003cspan class=\"x x-first x-last\"\u003equery\u003c/span\u003e results are discarded.","displayNoNewLineWarning" 8000 :false,"position":214,"left":1281,"right":1323},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1324,"text":"+ clause is specified, the command results are discarded.","html":"+ clause is specified, the \u003cspan class=\"x x-first x-last\"\u003ecommand\u003c/span\u003e results are discarded.","displayNoNewLineWarning":false,"position":215,"left":1281,"right":1324},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1325,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":216,"left":1282,"right":1325},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1326,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":217,"left":1283,"right":1326},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1327,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":218,"left":1284,"right":1327},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1328,"text":" If the \u003cliteral\u003eSTRICT\u003c/literal\u003e option is given, an error is reported","html":" If the \u0026lt;literal\u0026gt;STRICT\u0026lt;/literal\u0026gt; option is given, an error is reported","displayNoNewLineWarning":false,"position":219,"left":1285,"right":1328},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1286,"text":"- unless the query produces exactly one row.","html":"- unless the \u003cspan class=\"x x-first x-last\"\u003equery\u003c/span\u003e produces exactly one row.","displayNoNewLineWarning":false,"position":220,"left":1286,"right":1328},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1329,"text":"+ unless the command produces exactly one row.","html":"+ unless the \u003cspan class=\"x x-first x-last\"\u003ecommand\u003c/span\u003e produces exactly one row.","displayNoNewLineWarning":false,"position":221,"left":1286,"right":1329},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1330,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":222,"left":1287,"right":1330},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1331,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":223,"left":1288,"right":1331},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1332,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":224,"left":1289,"right":1332},{"stylingDirective":null,"type":"HUNK","blobLineNumber":1358,"text":"@@ -1316,17 +1359,23 @@ EXECUTE 'SELECT count(*) FROM '","html":"@@ -1316,17 +1359,23 @@ EXECUTE \u0026#39;SELECT count(*) FROM \u0026#39;","displayNoNewLineWarning":false,"position":225,"left":1315,"right":1358},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1359,"text":" USING checked_user, checked_date;","html":" USING checked_user, checked_date;","displayNoNewLineWarning":false,"position":226,"left":1316,"right":1359},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1360,"text":" \u003c/programlisting\u003e","html":" \u0026lt;/programlisting\u0026gt;","displayNoNewLineWarning":false,"position":227,"left":1317,"right":1360},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1361,"text":" A cleaner approach is to use \u003cfunction\u003eformat()\u003c/function\u003e's \u003cliteral\u003e%I\u003c/literal\u003e","html":" A cleaner approach is to use \u0026lt;function\u0026gt;format()\u0026lt;/function\u0026gt;\u0026#39;s \u0026lt;literal\u0026gt;%I\u0026lt;/literal\u0026gt;","displayNoNewLineWarning":false,"position":228,"left":1318,"right":1361},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1319,"text":"- specification for table or column names (strings separated by a","html":"- specification for table or column names (strings separated by a","displayNoNewLineWarning":false,"position":229,"left":1319,"right":1361},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1320,"text":"- newline are concatenated):","html":"- newline are concatenated):","displayNoNewLineWarning":false,"position":230,"left":1320,"right":1361},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1362,"text":"+ specification to insert table or column names with automatic quoting:","html":"+ specification to insert table or column names with automatic quoting:","displayNoNewLineWarning":false,"position":231,"left":1320,"right":1362},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1363,"text":" \u003cprogramlisting\u003e","html":" \u0026lt;programlisting\u0026gt;","displayNoNewLineWarning":false,"position":232,"left":1321,"right":1363},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1364,"text":" EXECUTE format('SELECT count(*) FROM %I '","html":" EXECUTE format(\u0026#39;SELECT count(*) FROM %I \u0026#39;","displayNoNewLineWarning":false,"position":233,"left":1322,"right":1364},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1365,"text":" 'WHERE inserted_by = $1 AND inserted \u0026lt;= $2', tabname)","html":" \u0026#39;WHERE inserted_by = $1 AND inserted \u0026amp;lt;= $2\u0026#39;, tabname)","displayNoNewLineWarning":false,"position":234,"left":1323,"right":1365},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1366,"text":" INTO c","html":" INTO c","displayNoNewLineWarning":false,"position":235,"left":1324,"right":1366},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1367,"text":" USING checked_user, checked_date;","html":" USING checked_user, checked_date;","displayNoNewLineWarning":false,"position":236,"left":1325,"right":1367},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1368,"text":" \u003c/programlisting\u003e","html":" \u0026lt;/programlisting\u0026gt;","displayNoNewLineWarning":false,"position":237,"left":1326,"right":1368},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1369,"text":"+ (This example relies on the SQL rule that string literals separated by a","html":"+ (This example relies on the SQL rule that string literals separated by a","displayNoNewLineWarning":false,"position":238,"left":1326,"right":1369},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1370,"text":"+ newline are implicitly concatenated.)","html":"+ newline are implicitly concatenated.)","displayNoNewLineWarning":false,"position":239,"left":1326,"right":1370},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1371,"text":"+ \u003c/para\u003e","html":"+ \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":240,"left":1326,"right":1371},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1372,"text":"+","html":"+","displayNoNewLineWarning":false,"position":241,"left":1326,"right":1372},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1373,"text":"+ \u003cpara\u003e","html":"+ \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":242,"left":1326,"right":1373},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1374,"text":" Another restriction on parameter symbols is that they only work in","html":" Another restriction on parameter symbols is that they only work in","displayNoNewLineWarning":false,"position":243,"left":1327,"right":1374},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1328,"text":"- \u003ccommand\u003eSELECT\u003c/command\u003e, \u003ccommand\u003eINSERT\u003c/command\u003e, \u003ccommand\u003eUPDATE\u003c/command\u003e, and","html":"- \u0026lt;command\u0026gt;SELECT\u0026lt;/command\u0026gt;, \u0026lt;command\u0026gt;INSERT\u0026lt;/command\u0026gt;, \u0026lt;command\u0026gt;UPDATE\u0026lt;/command\u0026gt;, and","displayNoNewLineWarning":false,"position":244,"left":1328,"right":1374},{"stylingDirective":null,"type":"DELETION","blobLineNumber":1329,"text":"- \u003ccommand\u003eDELETE\u003c/command\u003e commands. In other statement","html":"- \u0026lt;command\u0026gt;DELETE\u0026lt;/command\u0026gt; commands. In other statement","displayNoNewLineWarning":false,"position":245,"left":1329,"right":1374},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1375,"text":"+ optimizable SQL commands","html":"+ optimizable SQL commands","displayNoNewLineWarning":false,"position":246,"left":1329,"right":1375},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1376,"text":"+ (\u003ccommand\u003eSELECT\u003c/command\u003e, \u003ccommand\u003eINSERT\u003c/command\u003e, \u003ccommand\u003eUPDATE\u003c/command\u003e,","html":"+ (\u0026lt;command\u0026gt;SELECT\u0026lt;/command\u0026gt;, \u0026lt;command\u0026gt;INSERT\u0026lt;/command\u0026gt;, \u0026lt;command\u0026gt;UPDATE\u0026lt;/command\u0026gt;,","displayNoNewLineWarning":false,"position":247,"left":1329,"right":1376},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1377,"text":"+ \u003ccommand\u003eDELETE\u003c/command\u003e, and certain commands containing one of these).","html":"+ \u0026lt;command\u0026gt;DELETE\u0026lt;/command\u0026gt;, and certain commands containing one of these).","displayNoNewLineWarning":false,"position":248,"left":1329,"right":1377},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":1378,"text":"+ In other statement","html":"+ In other statement","displayNoNewLineWarning":false,"position":249,"left":1329,"right":1378},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1379,"text":" types (generically called utility statements), you must insert","html":" types (generically called utility statements), you must insert","displayNoNewLineWarning":false,"position":250,"left":1330,"right":1379},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1380,"text":" values textually even if they are just data values.","html":" values textually even if they are just data values.","displayNoNewLineWarning":false,"position":251,"left":1331,"right":1380},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":1381,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":252,"left":1332,"right":1381},{"stylingDirective":null,"type":"HUNK","blobLineNumber":2615,"text":"@@ -2567,7 +2616,7 @@ $$ LANGUAGE plpgsql;","html":"@@ -2567,7 +2616,7 @@ $$ LANGUAGE plpgsql;","displayNoNewLineWarning":false,"position":253,"left":2566,"right":2615},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":2616,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":254,"left":2567,"right":2616},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":2617,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":255,"left":2568,"right":2617},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":2618,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":256,"left":2569,"right":2618},{"stylingDirective":null,"type":"DELETION","blobLineNumber":2570,"text":"- \u003capplication\u003ePL/pgSQL\u003c/application\u003e variables are substituted into the query text,","html":"- \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; variables are \u003cspan class=\"x x-first x-last\"\u003esubstituted into the \u003c/span\u003equery \u003cspan class=\"x x-first x-last\"\u003etext\u003c/span\u003e,","displayNoNewLineWarning":false,"position":257,"left":2570,"right":2618},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":2619,"text":"+ \u003capplication\u003ePL/pgSQL\u003c/application\u003e variables are replaced by query parameters,","html":"+ \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; variables are \u003cspan class=\"x x-first x-last\"\u003ereplaced by \u003c/span\u003equery \u003cspan class=\"x x-first x-last\"\u003eparameters\u003c/span\u003e,","displayNoNewLineWarning":false,"position":258,"left":2570,"right":2619},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":2620,"text":" and the query plan is cached for possible re-use, as discussed in","html":" and the query plan is cached for possible re-use, as discussed in","displayNoNewLineWarning":false,"position":259,"left":2571,"right":2620},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":2621,"text":" detail in \u003cxref linkend=\"plpgsql-var-subst\"/\u003e and","html":" detail in \u0026lt;xref linkend=\u0026quot;plpgsql-var-subst\u0026quot;/\u0026gt; and","displayNoNewLineWarning":false,"position":260,"left":2572,"right":2621},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":2622,"text":" \u003cxref linkend=\"plpgsql-plan-caching\"/\u003e.","html":" \u0026lt;xref linkend=\u0026quot;plpgsql-plan-caching\u0026quot;/\u0026gt;.","displayNoNewLineWarning":false,"position":261,"left":2573,"right":2622},{"stylingDirective":null,"type":"HUNK","blobLineNumber":4691,"text":"@@ -4643,26 +4692,29 @@ CREATE EVENT TRIGGER snitch ON ddl_command_start EXECUTE FUNCTION snitch();","html":"@@ -4643,26 +4692,29 @@ CREATE EVENT TRIGGER snitch ON ddl_command_start EXECUTE FUNCTION snitch();","displayNoNewLineWarning":false,"position":262,"left":4642,"right":4691},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4692,"text":" SQL statements and expressions within a \u003capplication\u003ePL/pgSQL\u003c/application\u003e function","html":" SQL statements and expressions within a \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; function","displayNoNewLineWarning":false,"position":263,"left":4643,"right":4692},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4693,"text":" can refer to variables and parameters of the function. Behind the scenes,","html":" can refer to variables and parameters of the function. Behind the scenes,","displayNoNewLineWarning":false,"position":264,"left":4644,"right":4693},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4694,"text":" \u003capplication\u003ePL/pgSQL\u003c/application\u003e substitutes query parameters for such references.","html":" \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; substitutes query parameters for such references.","displayNoNewLineWarning":false,"position":265,"left":4645,"right":4694},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4646,"text":"- Parameters will only be substituted in places where a parameter or","html":"- \u003cspan class=\"x x-first x-last\"\u003eParameters \u003c/span\u003ewill only be substituted in places where \u003cspan class=\"x x-first x-last\"\u003ea parameter or\u003c/span\u003e","displayNoNewLineWarning":false,"position":266,"left":4646,"right":4694},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4647,"text":"- column reference is syntactically allowed. As an extreme case, consider","html":"- \u003cspan class=\"x x-first x-last\"\u003ecolumn reference is \u003c/span\u003esyntactically \u003cspan class=\"x x-first x-last\"\u003eallowed\u003c/span\u003e. As an extreme case, consider","displayNoNewLineWarning":false,"position":267,"left":4647,"right":4694},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4695,"text":"+ Query parameters will only be substituted in places where they are","html":"+ \u003cspan class=\"x x-first x-last\"\u003eQuery parameters \u003c/span\u003ewill only be substituted in places where \u003cspan class=\"x x-first x-last\"\u003ethey are\u003c/span\u003e","displayNoNewLineWarning":false,"position":268,"left":4647,"right":4695},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4696,"text":"+ syntactically permissible. As an extreme case, consider","html":"+ syntactically \u003cspan class=\"x x-first x-last\"\u003epermissible\u003c/span\u003e. As an extreme case, consider","displayNoNewLineWarning":false,"position":269,"left":4647,"right":4696},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4697,"text":" this example of poor programming style:","html":" this example of poor programming style:","displayNoNewLineWarning":false,"position":270,"left":4648,"right":4697},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4698,"text":" \u003cprogramlisting\u003e","html":" \u0026lt;programlisting\u0026gt;","displayNoNewLineWarning":false,"position":271,"left":4649,"right":4698},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4650,"text":"-INSERT INTO foo (foo) VALUES (foo);","html":"-INSERT INTO foo (foo) VALUES (foo);","displayNoNewLineWarning":false,"position":272,"left":4650,"right":4698},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4699,"text":"+INSERT INTO foo (foo) VALUES (foo(foo));","html":"+INSERT INTO foo (foo) VALUES (foo\u003cspan class=\"x x-first x-last\"\u003e(foo)\u003c/span\u003e);","displayNoNewLineWarning":false,"position":273,"left":4650,"right":4699},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4700,"text":" \u003c/programlisting\u003e","html":" \u0026lt;/programlisting\u0026gt;","displayNoNewLineWarning":false,"position":274,"left":4651,"right":4700},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4701,"text":" The first occurrence of \u003cliteral\u003efoo\u003c/literal\u003e must syntactically be a table","html":" The first occurrence of \u0026lt;literal\u0026gt;foo\u0026lt;/literal\u0026gt; must syntactically be a table","displayNoNewLineWarning":false,"position":275,"left":4652,"right":4701},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4702,"text":" name, so it will not be substituted, even if the function has a variable","html":" name, so it will not be substituted, even if the function has a variable","displayNoNewLineWarning":false,"position":276,"left":4653,"right":4702},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4703,"text":" named \u003cliteral\u003efoo\u003c/literal\u003e. The second occurrence must be the name of a","html":" named \u0026lt;literal\u0026gt;foo\u0026lt;/literal\u0026gt;. The second occurrence must be the name of a","displayNoNewLineWarning":false,"position":277,"left":4654,"right":4703},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4655,"text":"- column of the table, so it will not be substituted either. Only the","html":"- column of the table, so it will not be substituted either. Only the","displayNoNewLineWarning":false,"position":278,"left":4655,"right":4703},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4656,"text":"- third occurrence is a candidate to be a reference to the function's","html":"- third occurrence is a candidate to be a reference to the function\u0026#39;s","displayNoNewLineWarning":false,"position":279,"left":4656,"right":4703},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4657,"text":"- variable.","html":"- variable.","displayNoNewLineWarning":false,"position":280,"left":4657,"right":4703},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4704,"text":"+ column of that table, so it will not be substituted either. Likewise","html":"+ column of that table, so it will not be substituted either. Likewise","displayNoNewLineWarning":false,"position":281,"left":4657,"right":4704},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4705,"text":"+ the third occurrence must be a function name, so it also will not be","html":"+ the third occurrence must be a function name, so it also will not be","displayNoNewLineWarning":false,"position":282,"left":4657,"right":4705},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4706,"text":"+ substituted for. Only the last occurrence is a candidate to be a","html":"+ substituted for. Only the last occurrence is a candidate to be a","displayNoNewLineWarning":false,"position":283,"left":4657,"right":4706},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4707,"text":"+ reference to a variable of the \u003capplication\u003ePL/pgSQL\u003c/application\u003e","html":"+ reference to a variable of the \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt;","displayNoNewLineWarning":false,"position":284,"left":4657,"right":4707},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4708,"text":"+ function.","html":"+ function.","displayNoNewLineWarning":false,"position":285,"left":4657,"right":4708},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4709,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":286,"left":4658,"right":4709},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4710,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":287,"left":4659,"right":4710},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4660,"text":"- \u003cnote\u003e","html":"- \u0026lt;note\u0026gt;","displayNoNewLineWarning":false,"position":288,"left":4660,"right":4710},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4661,"text":"- \u003cpara\u003e","html":"- \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":289,"left":4661,"right":4710},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4662,"text":"- \u003cproductname\u003ePostgreSQL\u003c/productname\u003e versions before 9.0 would try","html":"- \u0026lt;productname\u0026gt;PostgreSQL\u0026lt;/productname\u0026gt; versions before 9.0 would try","displayNoNewLineWarning":false,"position":290,"left":4662,"right":4710},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4663,"text":"- to substitute the variable in all three cases, leading to syntax errors.","html":"- to substitute the variable in all three cases, leading to syntax errors.","displayNoNewLineWarning":false,"position":291,"left":4663,"right":4710},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4664,"text":"- \u003c/para\u003e","html":"- \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":292,"left":4664,"right":4710},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4665,"text":"- \u003c/note\u003e","html":"- \u0026lt;/note\u0026gt;","displayNoNewLineWarning":false,"position":293,"left":4665,"right":4710},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4711,"text":"+ \u003cpara\u003e","html":"+ \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":294,"left":4665,"right":4711},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4712,"text":"+ Another way to understand this is that variable substitution can only","html":"+ Another way to understand this is that variable substitution can only","displayNoNewLineWarning":false,"position":295,"left":4665,"right":4712},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4713,"text":"+ insert data values into a SQL command; it cannot dynamically change which","html":"+ insert data values into a SQL command; it cannot dynamically change which","displayNoNewLineWarning":false,"position":296,"left":4665,"right":4713},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4714,"text":"+ database objects are referenced by the command. (If you want to do","html":"+ database objects are referenced by the command. (If you want to do","displayNoNewLineWarning":false,"position":297,"left":4665,"right":4714},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4715,"text":"+ that, you must build a command string dynamically, as explained in","html":"+ that, you must build a command string dynamically, as explained in","displayNoNewLineWarning":false,"position":298,"left":4665,"right":4715},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4716,"text":"+ \u003cxref linkend=\"plpgsql-statements-executing-dyn\"/\u003e.)","html":"+ \u0026lt;xref linkend=\u0026quot;plpgsql-statements-executing-dyn\u0026quot;/\u0026gt;.)","displayNoNewLineWarning":false,"position":299,"left":4665,"right":4716},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4717,"text":"+ \u003c/para\u003e","html":"+ \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":300,"left":4665,"right":4717},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4718,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":301,"left":4666,"right":4718},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4719,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":302,"left":4667,"right":4719},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4720,"text":" Since the names of variables are syntactically no different from the names","html":" Since the names of variables are syntactically no different from the names","displayNoNewLineWarning":false,"position":303,"left":4668,"right":4720},{"stylingDirective":null,"type":"HUNK","blobLineNumber":4841,"text":"@@ -4790,7 +4842,7 @@ $$ LANGUAGE plpgsql;","html":"@@ -4790,7 +4842,7 @@ $$ LANGUAGE plpgsql;","displayNoNewLineWarning":false,"position":304,"left":4789,"right":4841},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4842,"text":" \u003c/para\u003e","html":" \u0026lt;/para\u0026gt;","displayNoNewLineWarning":false,"position":305,"left":4790,"right":4842},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4843,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":306,"left":4791,"right":4843},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4844,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":307,"left":4792,"right":4844},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4793,"text":"- Variable substitution does not happen in the command string given","html":"- Variable substitution does not happen in \u003cspan class=\"x x-first x-last\"\u003ethe\u003c/span\u003e command string given","displayNoNewLineWarning":false,"position":308,"left":4793,"right":4844},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4845,"text":"+ Variable substitution does not happen in a command string given","html":"+ Variable substitution does not happen in \u003cspan class=\"x x-first x-last\"\u003ea\u003c/span\u003e command string given","displayNoNewLineWarning":false,"position":309,"left":4793,"right":4845},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4846,"text":" to \u003ccommand\u003eEXECUTE\u003c/command\u003e or one of its variants. If you need to","html":" to \u0026lt;command\u0026gt;EXECUTE\u0026lt;/command\u0026gt; or one of its variants. If you need to","displayNoNewLineWarning":false,"position":310,"left":4794,"right":4846},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4847,"text":" insert a varying value into such a command, do so as part of","html":" insert a varying value into such a command, do so as part of","displayNoNewLineWarning":false,"position":311,"left":4795,"right":4847},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4848,"text":" constructing the string value, or use \u003cliteral\u003eUSING\u003c/literal\u003e, as illustrated in","html":" constructing the string value, or use \u0026lt;literal\u0026gt;USING\u0026lt;/literal\u0026gt;, as illustrated in","displayNoNewLineWarning":false,"position":312,"left":4796,"right":4848},{"stylingDirective":null,"type":"HUNK","blobLineNumber":4850,"text":"@@ -4799,7 +4851,10 @@ $$ LANGUAGE plpgsql;","html":"@@ -4799,7 +4851,10 @@ $$ LANGUAGE plpgsql;","displayNoNewLineWarning":false,"position":313,"left":4798,"right":4850},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4851,"text":" ","html":"\u003cbr\u003e","displayNoNewLineWarning":false,"position":314,"left":4799,"right":4851},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4852,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":315,"left":4800,"right":4852},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4853,"text":" Variable substitution currently works only in \u003ccommand\u003eSELECT\u003c/command\u003e,","html":" Variable substitution currently works only in \u0026lt;command\u0026gt;SELECT\u0026lt;/command\u0026gt;,","displayNoNewLineWarning":false,"position":316,"left":4801,"right":4853},{"stylingDirective":null,"type":"DELETION","blobLineNumber":4802,"text":"- \u003ccommand\u003eINSERT\u003c/command\u003e, \u003ccommand\u003eUPDATE\u003c/command\u003e, and \u003ccommand\u003eDELETE\u003c/command\u003e commands,","html":"- \u0026lt;command\u0026gt;INSERT\u0026lt;/command\u0026gt;, \u0026lt;command\u0026gt;UPDATE\u0026lt;/command\u0026gt;, and \u0026lt;command\u0026gt;DELETE\u0026lt;/command\u0026gt; commands,","displayNoNewLineWarning":false,"position":317,"left":4802,"right":4853},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4854,"text":"+ \u003ccommand\u003eINSERT\u003c/command\u003e, \u003ccommand\u003eUPDATE\u003c/command\u003e,","html":"+ \u0026lt;command\u0026gt;INSERT\u0026lt;/command\u0026gt;, \u0026lt;command\u0026gt;UPDATE\u0026lt;/command\u0026gt;,","displayNoNewLineWarning":false,"position":318,"left":4802,"right":4854},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4855,"text":"+ \u003ccommand\u003eDELETE\u003c/command\u003e, and commands containing one of","html":"+ \u0026lt;command\u0026gt;DELETE\u0026lt;/command\u0026gt;, and commands containing one of","displayNoNewLineWarning":false,"position":319,"left":4802,"right":4855},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4856,"text":"+ these (such as \u003ccommand\u003eEXPLAIN\u003c/command\u003e and \u003ccommand\u003eCREATE TABLE","html":"+ these (such as \u0026lt;command\u0026gt;EXPLAIN\u0026lt;/command\u0026gt; and \u0026lt;command\u0026gt;CREATE TABLE","displayNoNewLineWarning":false,"position":320,"left":4802,"right":4856},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":4857,"text":"+ ... AS SELECT\u003c/command\u003e),","html":"+ ... AS SELECT\u0026lt;/command\u0026gt;),","displayNoNewLineWarning":false,"position":321,"left":4802,"right":4857},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4858,"text":" because the main SQL engine allows query parameters only in these","html":" because the main SQL engine allows query parameters only in these","displayNoNewLineWarning":false,"position":322,"left":4803,"right":4858},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4859,"text":" commands. To use a non-constant name or value in other statement","html":" commands. To use a non-constant name or value in other statement","displayNoNewLineWarning":false,"position":323,"left":4804,"right":4859},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":4860,"text":" types (generically called utility statements), you must construct","html":" types (generically called utility statements), you must construct","displayNoNewLineWarning":false,"position":324,"left":4805,"right":4860},{"stylingDirective":null,"type":"HUNK","blobLineNumber":5368,"text":"@@ -5314,11 +5369,12 @@ HINT: Make sure the query returns the exact list of columns.","html":"@@ -5314,11 +5369,12 @@ HINT: Make sure the query returns the exact list of columns.","displayNoNewLineWarning":false,"position":325,"left":5313,"right":5368},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":5369,"text":" \u003clistitem\u003e","html":" \u0026lt;listitem\u0026gt;","displayNoNewLineWarning":false,"position":326,"left":5314,"right":5369},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":5370,"text":" \u003cpara\u003e","html":" \u0026lt;para\u0026gt;","displayNoNewLineWarning":false,"position":327,"left":5315,"right":5370},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":5371,"text":" If a name used in a SQL command could be either a column name of a","html":" If a name used in a SQL command could be either a column name of a","displayNoNewLineWarning":false,"position":328,"left":5316,"right":5371},{"stylingDirective":null,"type":"DELETION","blobLineNumber":5317,"text":"- table or a reference to a variable of the function,","html":"- table or a reference to a variable of the function,","displayNoNewLineWarning":false,"position":329,"left":5317,"right":5371},{"stylingDirective":null,"type":"DELETION","blobLineNumber":5318,"text":"- \ 8000 u003capplication\u003ePL/SQL\u003c/application\u003e treats it as a column name. This corresponds","html":"- \u0026lt;application\u0026gt;PL/SQL\u0026lt;/application\u0026gt; treats it as a column name. This corresponds","displayNoNewLineWarning":false,"position":330,"left":5318,"right":5371},{"stylingDirective":null,"type":"DELETION","blobLineNumber":5319,"text":"- to \u003capplication\u003ePL/pgSQL\u003c/application\u003e's","html":"- to \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt;\u0026#39;s","displayNoNewLineWarning":false,"position":331,"left":5319,"right":5371},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":5372,"text":"+ table used in the command or a reference to a variable of the function,","html":"+ table used in the command or a reference to a variable of the function,","displayNoNewLineWarning":false,"position":332,"left":5319,"right":5372},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":5373,"text":"+ \u003capplication\u003ePL/SQL\u003c/application\u003e treats it as a column name.","html":"+ \u0026lt;application\u0026gt;PL/SQL\u0026lt;/application\u0026gt; treats it as a column name.","displayNoNewLineWarning":false,"position":333,"left":5319,"right":5373},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":5374,"text":"+ By default, \u003capplication\u003ePL/pgSQL\u003c/application\u003e will throw an error","html":"+ By default, \u0026lt;application\u0026gt;PL/pgSQL\u0026lt;/application\u0026gt; will throw an error","displayNoNewLineWarning":false,"position":334,"left":5319,"right":5374},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":5375,"text":"+ complaining that the name is ambiguous. You can specify","html":"+ complaining that the name is ambiguous. You can specify","displayNoNewLineWarning":false,"position":335,"left":5319,"right":5375},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":5376,"text":" \u003cliteral\u003eplpgsql.variable_conflict\u003c/literal\u003e = \u003cliteral\u003euse_column\u003c/literal\u003e","html":" \u0026lt;literal\u0026gt;plpgsql.variable_conflict\u0026lt;/literal\u0026gt; = \u0026lt;literal\u0026gt;use_column\u0026lt;/literal\u0026gt;","displayNoNewLineWarning":false,"position":336,"left":5320,"right":5376},{"stylingDirective":null,"type":"DELETION","blobLineNumber":5321,"text":"- behavior, which is not the default,","html":"- \u003cspan class=\"x x-first x-last\"\u003ebehavior, which is not the default\u003c/span\u003e,","displayNoNewLineWarning":false,"position":337,"left":5321,"right":5376},{"stylingDirective":null,"type":"ADDITION","blobLineNumber":5377,"text":"+ to change this behavior to match \u003capplication\u003ePL/SQL\u003c/application\u003e,","html":"+ \u003cspan class=\"x x-first x-last\"\u003eto change this behavior to match \u0026lt;application\u0026gt;PL/SQL\u0026lt;/application\u0026gt;\u003c/span\u003e,","displayNoNewLineWarning":false,"position":338,"left":5321,"right":5377},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":5378,"text":" as explained in \u003cxref linkend=\"plpgsql-var-subst\"/\u003e.","html":" as explained in \u0026lt;xref linkend=\u0026quot;plpgsql-var-subst\u0026quot;/\u0026gt;.","displayNoNewLineWarning":false,"position":339,"left":5322,"right":5378},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":5379,"text":" It's often best to avoid such ambiguities in the first place,","html":" It\u0026#39;s often best to avoid such ambiguities in the first place,","displayNoNewLineWarning":false,"position":340,"left":5323,"right":5379},{"stylingDirective":null,"type":"CONTEXT","blobLineNumber":5380,"text":" but if you have to port a large amount of code that depends on","html":" but if you have to port a large amount of code that depends on","displayNoNewLineWarning":false,"position":341,"left":5324,"right":5380}],"diffNumber":0,"diffSize":"0 Bytes","isBinary":false,"isTooBig":false,"collapsed":false,"isSubmodule":false,"lineCount":6064,"linesChanged":172,"newTreeEntry":{"lineCount":6064,"path":"doc/src/sgml/plpgsql.sgml","mode":100644,"isGenerated":false},"oldTreeEntry":{"lineCount":0,"path":"doc/src/sgml/plpgsql.sgml","mode":100644},"linesAdded":114,"linesDeleted":58,"path":"doc/src/sgml/plpgsql.sgml","pathDigest":"a1d161c0a6f7463af6d81d54c42bc8a2b6021e64af07fd0ec43e5a2c2394f8d0","status":"MODIFIED","truncatedReason":null,"oldOid":"7f7f25f15edb6eacec58179ef5285e874aa4435b","newOid":"c783e656d41816b0328cb4bff27f11b70200770e","copilotChatReference":null,"deletedSha":"7f7f25f15edb6eacec58179ef5285e874aa4435b","canToggleRichDiff":false,"defaultToRichDiff":false,"proseDifffHtml":null,"renderInfo":null,"dependencyDiffPath":null,"submodule":null}],"splitViewPreference":"unified","ignoreWhitespace":false,"repoOwnerGlobalRelayId":"MDEyOk9yZ2FuaXphdGlvbjE3NzU0Mw==","commentsPreference":"visible","diffLineSpacingPreference":"relaxed","useMonospaceFont":false,"pasteUrlLinkAsPlainText":false,"userNotices":[],"path":"/postgres/postgres/commit/c783e656d41816b0328cb4bff27f11b70200770e","fileTreeExpanded":true,"headerInfo":{"additions":114,"deletions":58,"filesChanged":1,"filesChangedString":"1"},"moreDiffsToLoad":false,"asyncDiffLoadInfo":{"startIndex":1,"truncated":false,"byteCount":17409,"lineShownCount":342},"commentInfo":{"canComment":false,"locked":false,"canLock":false,"repoArchived":false},"csrf_tokens":{"/users/diffview?diff=split":{"post":"QAFOWlp0Mepj064yOEygBF_24fO9VqkINw06h8gk4fdr0vE4-l8or1Rwh2IR9Bgau8c2TLr7wubdgjLF84xe4A"},"/users/diffview?diff=unified":{"post":"EgRz7PLorsR2KbLbP1GGazP5wAcWY8m4XCuYQ53D_ow518yOUsO3gUGKm4sW6T5118gXuBHOola2pJABpmtBmw"},"/notifications/thread":{"post":"5Z_phChKPRoJoZEY_4ABlwKj_6MO2Kn6ACSZKUVomjA1VrGK1Rn4ngCnRrcbipa71ufHlOK0HVhSo2rICJ6KTw"}}},"title":"Doc: improve discussion of variable substitution in PL/pgSQL. · postgres/postgres@c783e65","appPayload":{"helpUrl":"https://docs.github.com","findInDiffWorkerPath":"/assets-cdn/worker/find-in-diff-worker-2bfe39677d14.js","enabled_features":{"diff_ux_refresh_beta":false,"diff_inline_comments":true,"diff_ux_refresh_ssr_five":false,"diff_ux_refresh_ssr_ten":false,"react_diff_line_type_character_correction":true}}}

Commit c783e65

Browse files
committed
Doc: improve discussion of variable substitution in PL/pgSQL.
This was a bit disjointed, partly because of a not-well-considered decision to document SQL commands that don't return result rows as though they had nothing in common with commands that do. Rearrange so that we have one discussion of variable substitution that clearly applies to all types of SQL commands, and then handle the question of processing command output separately. Clarify that EXPLAIN, CREATE TABLE AS SELECT, and similar commands that incorporate an optimizable statement will act like optimizable statements for the purposes of variable substitution. Do a bunch of minor wordsmithing in the same area. David Johnston and Tom Lane, reviewed by Pavel Stehule and David Steele Discussion: https://postgr.es/m/CAKFQuwYvMKucM5fnZvHSo-ah4S=_n9gmKeu6EAo=_fTrohunqQ@mail.gmail.com
1 parent 7f7f25f commit c783e65

File tree

1 file changed

+114
-58
lines changed

1 file changed

+114
-58
lines changed

doc/src/sgml/plpgsql.sgml

Lines changed: 114 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,7 @@ SELECT <replaceable>expression</replaceable>
894894
</synopsis>
895895
to the main SQL engine. While forming the <command>SELECT</command> command,
896896
any occurrences of <application>PL/pgSQL</application> variable names
897-
are replaced by parameters, as discussed in detail in
897+
are replaced by query parameters, as discussed in detail in
898898
<xref linkend="plpgsql-var-subst"/>.
899899
This allows the query plan for the <command>SELECT</command> to
900900
be prepared just once and then reused for subsequent
@@ -946,8 +946,7 @@ IF count(*) &gt; 0 FROM my_table THEN ...
946946
<application>PL/pgSQL</application>.
947947
Anything not recognized as one of these statement types is presumed
948948
to be an SQL command and is sent to the main database engine to execute,
949-
as described in <xref linkend="plpgsql-statements-sql-noresult"/>
950-
and <xref linkend="plpgsql-statements-sql-onerow"/>.
949+
as described in <xref linkend="plpgsql-statements-general-sql"/>.
951950
</para>
952951

953952
<sect2 id="plpgsql-statements-assignment">
@@ -993,31 +992,78 @@ complex_array[n].realpart = 12.3;
993992
</para>
994993
</sect2>
995994

996-
<sect2 id="plpgsql-statements-sql-noresult">
997-
<title>Executing a Command with No Result</title>
995+
<sect2 id="plpgsql-statements-general-sql">
996+
<title>Executing SQL Commands</title>
998997

999998
<para>
1000-
For any SQL command that does not return rows, for example
1001-
<command>INSERT</command> without a <literal>RETURNING</literal> clause, you can
1002-
execute the command within a <application>PL/pgSQL</application> function
1003-
just by writing the command.
999+
In general, any SQL command that does not return rows can be executed
1000+
within a <application>PL/pgSQL</application> function just by writing
1001+
the command. For example, you could create and fill a table by writing
1002+
<programlisting>
1003+
CREATE TABLE mytable (id int primary key, data text);
1004+
INSERT INTO mytable VALUES (1,'one'), (2,'two');
1005+
</programlisting>
10041006
</para>
10051007

10061008
<para>
1007-
Any <application>PL/pgSQL</application> variable name appearing
1008-
in the command text is treated as a parameter, and then the
1009+
If the command does return rows (for example <command>SELECT</command>,
1010+
or <command>INSERT</command>/<command>UPDATE</command>/<command>DELETE</command>
1011+
with <literal>RETURNING</literal>), there are two ways to proceed.
1012+
When the command will return at most one row, or you only care about
1013+
the first row of output, write the command as usual but add
1014+
an <literal>INTO</literal> clause to capture the output, as described
1015+
in <xref linkend="plpgsql-statements-sql-onerow"/>.
1016+
To process all of the output rows, write the command as the data
1017+
source for a <command>FOR</command> loop, as described in
1018+
<xref linkend="plpgsql-records-iterating"/>.
1019+
</para>
1020+
1021+
<para>
1022+
Usually it is not sufficient just to execute statically-defined SQL
1023+
commands. Typically you'll want a command to use varying data values,
1024+
or even to vary in more fundamental ways such as by using different
1025+
table names at different times. Again, there are two ways to proceed
1026+
depending on the situation.
1027+
</para>
1028+
1029+
<para>
1030+
<application>PL/pgSQL</application> variable values can be
1031+
automatically inserted into optimizable SQL commands, which
1032+
are <command>SELECT</command>, <command>INSERT</command>,
1033+
<command>UPDATE</command>, <command>DELETE</command>, and certain
1034+
utility commands that incorporate one of these, such
1035+
as <command>EXPLAIN</command> and <command>CREATE TABLE ... AS
1036+
SELECT</command>. In these commands,
1037+
any <application>PL/pgSQL</application> variable name appearing
1038+
in the command text is replaced by a query parameter, and then the
10091039
current value of the variable is provided as the parameter value
10101040
at run time. This is exactly like the processing described earlier
10111041
for expressions; for details see <xref linkend="plpgsql-var-subst"/>.
10121042
</para>
10131043

10141044
<para>
1015-
When executing a SQL command in this way,
1045+
When executing an optimizable SQL command in this way,
10161046
<application>PL/pgSQL</application> may cache and re-use the execution
10171047
plan for the command, as discussed in
10181048
<xref linkend="plpgsql-plan-caching"/>.
10191049
</para>
10201050

1051+
<para>
1052+
Non-optimizable SQL commands (also called utility commands) are not
1053+
capable of accepting query parameters. So automatic substitution
1054+
of <application>PL/pgSQL</application> variables does not work in such
1055+
commands. To include non-constant text in a utility command executed
1056+
from <application>PL/pgSQL</application>, you must build the utility
1057+
command as a string and then <command>EXECUTE</command> it, as
1058+
discussed in <xref linkend="plpgsql-statements-executing-dyn"/>.
1059+
</para>
1060+
1061+
<para>
1062+
<command>EXECUTE</command> must also be used if you want to modify
1063+
the command in some other way than supplying a data value, for example
1064+
by changing a table name.
1065+
</para>
1066+
10211067
<para>
10221068
Sometimes it is useful to evaluate an expression or <command>SELECT</command>
10231069
query but discard the result, for example when calling a function
@@ -1037,7 +1083,7 @@ PERFORM <replaceable>query</replaceable>;
10371083
place the query in parentheses. (In this case, the query can only
10381084
return one row.)
10391085
<application>PL/pgSQL</application> variables will be
1040-
substituted into the query just as for commands that return no result,
1086+
substituted into the query just as described above,
10411087
and the plan is cached in the same way. Also, the special variable
10421088
<literal>FOUND</literal> is set to true if the query produced at
10431089
least one row, or false if it produced no rows (see
@@ -1065,7 +1111,7 @@ PERFORM create_mv('cs_session_page_requests_mv', my_query);
10651111
</sect2>
10661112

10671113
<sect2 id="plpgsql-statements-sql-onerow">
1068-
<title>Executing a Query with a Single-Row Result</title>
1114+
<title>Executing a Command with a Single-Row Result</title>
10691115

10701116
<indexterm zone="plpgsql-statements-sql-onerow">
10711117
<primary>SELECT INTO</primary>
@@ -1094,12 +1140,13 @@ DELETE ... RETURNING <replaceable>expressions</replaceable> INTO <optional>STRIC
10941140
variable, or a comma-separated list of simple variables and
10951141
record/row fields.
10961142
<application>PL/pgSQL</application> variables will be
1097-
substituted into the rest of the query, and the plan is cached,
1098-
just as described above for commands that do not return rows.
1143+
substituted into the rest of the command (that is, everything but the
1144+
<literal>INTO</literal> clause) just as described above,
1145+
and the plan is cached in the same way.
10991146
This works for <command>SELECT</command>,
11001147
<command>INSERT</command>/<command>UPDATE</command>/<command>DELETE</command> with
1101-
<literal>RETURNING</literal>, and utility commands that return row-set
1102-
results (such as <command>EXPLAIN</command>).
1148+
<literal>RETURNING</literal>, and certain utility commands
1149+
that return row sets, such as <command>EXPLAIN</command>.
11031150
Except for the <literal>INTO</literal> clause, the SQL command is the same
11041151
as it would be written outside <application>PL/pgSQL</application>.
11051152
</para>
@@ -1117,11 +1164,12 @@ DELETE ... RETURNING <replaceable>expressions</replaceable> INTO <optional>STRIC
11171164
</tip>
11181165

11191166
<para>
1120-
If a row or a variable list is used as target, the query's result columns
1167+
If a row variable or a variable list is used as target,
1168+
the command's result columns
11211169
must exactly match the structure of the target as to number and data
11221170
types, or else a run-time error
11231171
occurs. When a record variable is the target, it automatically
1124-
configures itself to the row type of the query result columns.
1172+
configures itself to the row type of the command's result columns.
11251173
</para>
11261174

11271175
<para>
@@ -1137,7 +1185,7 @@ DELETE ... RETURNING <replaceable>expressions</replaceable> INTO <optional>STRIC
11371185
<para>
11381186
If <literal>STRICT</literal> is not specified in the <literal>INTO</literal>
11391187
clause, then <replaceable>target</replaceable> will be set to the first
1140-
row returned by the query, or to nulls if the query returned no rows.
1188+
row returned by the command, or to nulls if the command returned no rows.
11411189
(Note that <quote>the first row</quote> is not
11421190
well-defined unless you've used <literal>ORDER BY</literal>.) Any result rows
11431191
after the first row are discarded.
@@ -1152,7 +1200,7 @@ IF NOT FOUND THEN
11521200
END IF;
11531201
</programlisting>
11541202

1155-
If the <literal>STRICT</literal> option is specified, the query must
1203+
If the <literal>STRICT</literal> option is specified, the command must
11561204
return exactly one row or a run-time error will be reported, either
11571205
<literal>NO_DATA_FOUND</literal> (no rows) or <literal>TOO_MANY_ROWS</literal>
11581206
(more than one row). You can use an exception block if you wish
@@ -1186,7 +1234,7 @@ END;
11861234
then when an error is thrown because the requirements
11871235
of <literal>STRICT</literal> are not met, the <literal>DETAIL</literal> part of
11881236
the error message will include information about the parameters
1189-
passed to the query.
1237+
passed to the command.
11901238
You can change the <literal>print_strict_params</literal>
11911239
setting for all functions by setting
11921240
<varname>plpgsql.print_strict_params</varname>, though only subsequent
@@ -1220,11 +1268,6 @@ CONTEXT: PL/pgSQL function get_userid(text) line 6 at SQL statement
12201268
</para>
12211269
</note>
12221270

1223-
<para>
1224-
To handle cases where you need to process multiple result rows
1225-
from a SQL query, see <xref linkend="plpgsql-records-iterating"/>.
1226-
</para>
1227-
12281271
</sect2>
12291272

12301273
<sect2 id="plpgsql-statements-executing-dyn">
@@ -1270,20 +1313,20 @@ EXECUTE <replaceable class="command">command-string</replaceable> <optional> INT
12701313

12711314
<para>
12721315
The <literal>INTO</literal> clause specifies where the results of
1273-
a SQL command returning rows should be assigned. If a row
1316+
a SQL command returning rows should be assigned. If a row variable
12741317
or variable list is provided, it must exactly match the structure
1275-
of the query's results (when a
1276-
record variable is used, it will configure itself to match the
1277-
result structure automatically). If multiple rows are returned,
1318+
of the command's results; if a
1319+
record variable is provided, it will configure itself to match the
1320+
result structure automatically. If multiple rows are returned,
12781321
only the first will be assigned to the <literal>INTO</literal>
1279-
variable. If no rows are returned, NULL is assigned to the
1322+
variable(s). If no rows are returned, NULL is assigned to the
12801323
<literal>INTO</literal> variable(s). If no <literal>INTO</literal>
1281-
clause is specified, the query results are discarded.
1324+
clause is specified, the command results are discarded.
12821325
</para>
12831326

12841327
<para>
12851328
If the <literal>STRICT</literal> option is given, an error is reported
1286-
unless the query produces exactly one row.
1329+
unless the command produces exactly one row.
12871330
</para>
12881331

12891332
<para>
@@ -1316,17 +1359,23 @@ EXECUTE 'SELECT count(*) FROM '
13161359
USING checked_user, checked_date;
13171360
</programlisting>
13181361
A cleaner approach is to use <function>format()</function>'s <literal>%I</literal>
1319-
specification for table or column names (strings separated by a
1320-
newline are concatenated):
1362+
specification to insert table or column names with automatic quoting:
13211363
<programlisting>
13221364
EXECUTE format('SELECT count(*) FROM %I '
13231365
'WHERE inserted_by = $1 AND inserted &lt;= $2', tabname)
13241366
INTO c
13251367
USING checked_user, checked_date;
13261368
</programlisting>
1369+
(This example relies on the SQL rule that string literals separated by a
1370+
newline are implicitly concatenated.)
1371+
</para>
1372+
1373+
<para>
13271374
Another restriction on parameter symbols is that they only work in
1328-
<command>SELECT</command>, <command>INSERT</command>, <command>UPDATE</command>, and
1329-
<command>DELETE</command> commands. In other statement
1375+
optimizable SQL commands
1376+
(<command>SELECT</command>, <command>INSERT</command>, <command>UPDATE</command>,
1377+
<command>DELETE</command>, and certain commands containing one of these).
1378+
In other statement
13301379
types (generically called utility statements), you must insert
13311380
values textually even if they are just data values.
13321381
</para>
@@ -2567,7 +2616,7 @@ $$ LANGUAGE plpgsql;
25672616
</para>
25682617

25692618
<para>
2570-
<application>PL/pgSQL</application> variables are substituted into the query text,
2619+
<application>PL/pgSQL</application> variables are replaced by query parameters,
25712620
and the query plan is cached for possible re-use, as discussed in
25722621
detail in <xref linkend="plpgsql-var-subst"/> and
25732622
<xref linkend="plpgsql-plan-caching"/>.
@@ -4643,26 +4692,29 @@ CREATE EVENT TRIGGER snitch ON ddl_command_start EXECUTE FUNCTION snitch();
46434692
SQL statements and expressions within a <application>PL/pgSQL</application> function
46444693
can refer to variables and parameters of the function. Behind the scenes,
46454694
<application>PL/pgSQL</application> substitutes query parameters for such references.
4646-
Parameters will only be substituted in places where a parameter or
4647-
column reference is syntactically allowed. As an extreme case, consider
4695+
Query parameters will only be substituted in places where they are
4696+
syntactically permissible. As an extreme case, consider
46484697
this example of poor programming style:
46494698
<programlisting>
4650-
INSERT INTO foo (foo) VALUES (foo);
4699+
INSERT INTO foo (foo) VALUES (foo(foo));
46514700
</programlisting>
46524701
The first occurrence of <literal>foo</literal> must syntactically be a table
46534702
name, so it will not be substituted, even if the function has a variable
46544703
named <literal>foo</literal>. The second occurrence must be the name of a
4655-
column of the table, so it will not be substituted either. Only the
4656-
third occurrence is a candidate to be a reference to the function's
4657-
variable.
4704+
column of that table, so it will not be substituted either. Likewise
4705+
the third occurrence must be a function name, so it also will not be
4706+
substituted for. Only the last occurrence is a candidate to be a
4707+
reference to a variable of the <application>PL/pgSQL</application>
4708+
function.
46584709
</para>
46594710

4660-
<note>
4661-
<para>
4662-
<productname>PostgreSQL</productname> versions before 9.0 would try
4663-
to substitute the variable in all three cases, leading to syntax errors.
4664-
</para>
4665-
</note>
4711+
<para>
4712+
Another way to understand this is that variable substitution can only
4713+
insert data values into a SQL command; it cannot dynamically change which
4714+
database objects are referenced by the command. (If you want to do
4715+
that, you must build a command string dynamically, as explained in
4716+
<xref linkend="plpgsql-statements-executing-dyn"/>.)
4717+
</para>
46664718

46674719
<para>
46684720
Since the names of variables are syntactically no different from the names
@@ -4790,7 +4842,7 @@ $$ LANGUAGE plpgsql;
47904842
</para>
47914843

47924844
<para>
4793-
Variable substitution does not happen in the command string given
4845+
Variable substitution does not happen in a command string given
47944846
to <command>EXECUTE</command> or one of its variants. If you need to
47954847
insert a varying value into such a command, do so as part of
47964848
constructing the string value, or use <literal>USING</literal>, as illustrated in
@@ -4799,7 +4851,10 @@ $$ LANGUAGE plpgsql;
47994851

48004852
<para>
48014853
Variable substitution currently works only in <command>SELECT</command>,
4802-
<command>INSERT</command>, <command>UPDATE</command>, and <command>DELETE</command> commands,
4854+
<command>INSERT</command>, <command>UPDATE</command>,
4855+
<command>DELETE</command>, and commands containing one of
4856+
these (such as <command>EXPLAIN</command> and <command>CREATE TABLE
4857+
... AS SELECT</command>),
48034858
because the main SQL engine allows query parameters only in these
48044859
commands. To use a non-constant name or value in other statement
48054860
types (generically called utility statements), you must construct
@@ -5314,11 +5369,12 @@ HINT: Make sure the query returns the exact list of columns.
53145369
<listitem>
53155370
<para>
53165371
If a name used in a SQL command could be either a column name of a
5317-
table or a reference to a variable of the function,
5318-
<application>PL/SQL</application> treats it as a column name. This corresponds
5319-
to <application>PL/pgSQL</application>'s
5372+
table used in the command or a reference to a variable of the function,
5373+
<application>PL/SQL</application> treats it as a column name.
5374+
By default, <application>PL/pgSQL</application> will throw an error
5375+
complaining that the name is ambiguous. You can specify
53205376
<literal>plpgsql.variable_conflict</literal> = <literal>use_column</literal>
5321-
behavior, which is not the default,
5377+
to change this behavior to match <application>PL/SQL</application>,
53225378
as explained in <xref linkend="plpgsql-var-subst"/>.
53235379
It's often best to avoid such ambiguities in the first place,
53245380
but if you have to port a large amount of code that depends on

0 commit comments

Comments
 (0)
0