
PL/pgSQL variable values can be automatically inserted into optimizable SQL commands, which are SELECT, INSERT, UPDATE, DELETE, MERGE, and certain utility commands that incorporate one of these, such as EXPLAIN and CREATE TABLE. Again, there are two ways to proceed depending on the situation. Typically you'll want a command to use varying data values, or even to vary in more fundamental ways such as by using different table names at different times. Usually it is not sufficient just to execute statically-defined SQL commands. To process all of the output rows, write the command as the data source for a FOR loop, as described in Section 43.6.6. When the command will return at most one row, or you only care about the first row of output, write the command as usual but add an INTO clause to capture the output, as described in Section 43.5.3. If the command does return rows (for example SELECT, or INSERT/ UPDATE/ DELETE with RETURNING), there are two ways to proceed. INSERT INTO mytable VALUES (1,'one'), (2,'two') For example, you could create and fill a table by writingĬREATE TABLE mytable (id int primary key, data text) In general, any SQL command that does not return rows can be executed within a PL/pgSQL function just by writing the command. Note that this could result in run-time errors generated by the input function, if the string form of the result value is not acceptable to the input function. If no assignment cast is known for the pair of data types involved, the PL/pgSQL interpreter will attempt to convert the result value textually, that is by applying the result type's output function followed by the variable type's input function. If the expression's result data type doesn't match the variable's data type, the value will be coerced as though by an assignment cast (see Section 10.4). Equal ( =) can be used instead of PL/SQL-compliant :=. The target variable can be a simple variable (optionally qualified with a block name), a field of a row or record target, or an element or slice of an array target.

The expression must yield a single value (possibly a row value, if the variable is a row or record variable).

However, the thing is that CREATE INDEX CONCURRENTLY is not atomic: if an attempt to deploy it fails, then the index is going to remain to be defined – in the INVALID state.An assignment of a value to a PL/pgSQL variable is written as: variable expression Īs explained previously, the expression in such a statement is evaluated by means of an SQL SELECT command sent to the main database engine. In such cases, it is tempting to use CREATE INDEX CONCURRENTLY IF NOT EXISTS. It is not uncommon to see how DBAs try various index ideas right on the production database, trying to find a band-aid for some suboptimal query, and then, once found, they suggest developers include the index to migrations – just to "register" it. Example 3: CREATE INDEX CONCURRENTLY IF NOT EXISTS įor large tables under load, it is recommended to use CREATE INDEX CONCURRENTLY – it is going to work longer that CREATE INEDEX but it won't cause downtime. As a result, automated testing is not going to catch the problem, and this wrong change has risks to be released.

This is not what we expected! For such time of mistakes, we do need to have an error in CI tests - bug IF EXISTS is going to "mask" the problem.

But what if mytable was created by another DB schema migration long ago? If the "undo" step needs to be executed somewhere, we are going to drop that table.
