{"Entry":{"collection":"sql","key":"create-policy","name":"CREATE POLICY","aliases":["createpolicy"],"metadata":{"aliases":["createpolicy"],"changed_in":["10","14"],"changes":[{"from":"9.4","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":[],"removed":[]},"status":"added","synopsis":null,"to":"9.5"},{"from":"9.6","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters"],"removed":[]},"status":"changed","synopsis":{"added":["[ AS { PERMISSIVE | RESTRICTIVE } ]"],"removed":[]},"to":"10"},{"from":"11","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes"],"removed":[]},"status":"changed","synopsis":null,"to":"12"},{"from":"12","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters"],"removed":[]},"status":"changed","synopsis":null,"to":"13"},{"from":"13","purpose_changed":true,"renamed":null,"sections":{"added":[],"changed":["description","parameters"],"removed":[]},"status":"changed","synopsis":{"added":["[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]"],"removed":[]},"to":"14"},{"from":"14","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes"],"removed":[]},"status":"changed","synopsis":null,"to":"15"},{"from":"15","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters"],"removed":[]},"status":"changed","synopsis":null,"to":"16"},{"from":"16","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes"],"removed":[]},"status":"changed","synopsis":null,"to":"17"},{"from":"17","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters"],"removed":[]},"status":"changed","synopsis":null,"to":"18"},{"from":"18","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes"],"removed":[]},"status":"changed","synopsis":null,"to":"19"},{"from":"19","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters"],"removed":[]},"status":"changed","synopsis":null,"to":"20"}],"content_hash":"2abd2a3c23ee99dfd5ed714a6257df7bb166ac4ca42911f32a9fec7b47eaf1c5","editorial":{},"first_version":"9.5","group":"role","imported_at":"2026-09-30T17:43:38.120845+08:00","last_version":"20","name":"CREATE POLICY","object":"POLICY","position":5009,"present_in":["9.5","9.6","10","11","12","13","14","15","16","17","18","19","20"],"purpose":"define a new row-level security policy for a table","purpose_zh":"","related":["alter-policy","drop-policy","alter-table"],"slug":"create-policy","source_rev":"a709ab85","synopsis":"CREATE POLICY name ON table_name\n[ AS { PERMISSIVE | RESTRICTIVE } ]\n[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]\n[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]\n[ USING ( using_expression ) ]\n[ WITH CHECK ( check_expression ) ]","verb":"CREATE"}},"Definition":{"Collection":"sql","Key":"create-policy","SourceDatabase":"center","Version":"18","SourceTable":"sqlcmd","SourceKey":"create-policy","SourceRevision":"a709ab85","Facts":{"anchor":"SQL-CREATEPOLICY","file":"sql-createpolicy.html","lang":"en","name":"CREATE POLICY","purpose":"define a new row-level security policy for a table","purpose_zh":"","related":["alter-policy","drop-policy","alter-table"],"sections":[{"html":"\u003cp\u003eThe \u003ccode class=\"command\"\u003eCREATE POLICY\u003c/code\u003e command defines a new row-level security policy for a table. Note that row-level security must be enabled on the table (using \u003ccode class=\"command\"\u003eALTER TABLE ... ENABLE ROW LEVEL SECURITY\u003c/code\u003e) in order for created policies to be applied.\u003c/p\u003e\u003cp\u003eA policy grants the permission to select, insert, update, or delete rows that match the relevant policy expression. Existing table rows are checked against the expression specified in \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e, while new rows that would be created via \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e or \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e are checked against the expression specified in \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e. When a \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expression returns true for a given row then that row is visible to the user, while if false or null is returned then the row is not visible. Typically, no error occurs when a row is not visible, but see \u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" title=\"Table 300. Policies Applied by Command Type\"\u003eTable 300\u003c/a\u003e for exceptions. When a \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expression returns true for a row then that row is inserted or updated, while if false or null is returned then an error occurs.\u003c/p\u003e\u003cp\u003eFor \u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e, \u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e, and \u003ccode class=\"command\"\u003eMERGE\u003c/code\u003e statements, \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expressions are enforced after \u003ccode class=\"literal\"\u003eBEFORE\u003c/code\u003e triggers are fired, and before any actual data modifications are made. Thus a \u003ccode class=\"literal\"\u003eBEFORE ROW\u003c/code\u003e trigger may modify the data to be inserted, affecting the result of the security policy check. \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expressions are enforced before any other constraints.\u003c/p\u003e\u003cp\u003ePolicy names are per-table. Therefore, one policy name can be used for many different tables and have a definition for each table which is appropriate to that table.\u003c/p\u003e\u003cp\u003ePolicies can be applied for specific commands or for specific roles. The default for newly created policies is that they apply for all commands and roles, unless otherwise specified. Multiple policies may apply to a single command; see below for more details. \u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" title=\"Table 300. Policies Applied by Command Type\"\u003eTable 300\u003c/a\u003e summarizes how the different types of policy apply to specific commands.\u003c/p\u003e\u003cp\u003eFor policies that can have both \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e and \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expressions (\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e and \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e), if no \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expression is defined, then the \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expression will be used both to determine which rows are visible (normal \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e case) and which new rows will be allowed to be added (\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e case).\u003c/p\u003e\u003cp\u003eIf row-level security is enabled for a table, but no applicable policies exist, a \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003edefault deny\u003c/span\u003e”\u003c/span\u003e policy is assumed, so that no rows will be visible or updatable.\u003c/p\u003e","key":"description","title":"Description"},{"html":"\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name of the policy to be created. This must be distinct from the name of any other policy for the table.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003etable_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name (optionally schema-qualified) of the table the policy applies to.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003ePERMISSIVE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eSpecify that the policy is to be created as a permissive policy. All permissive policies which are applicable to a given query will be combined together using the Boolean \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003eOR\u003c/span\u003e”\u003c/span\u003e operator. By creating permissive policies, administrators can add to the set of records which can be accessed. Policies are permissive by default.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eRESTRICTIVE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eSpecify that the policy is to be created as a restrictive policy. All restrictive policies which are applicable to a given query will be combined together using the Boolean \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003eAND\u003c/span\u003e”\u003c/span\u003e operator. By creating restrictive policies, administrators can reduce the set of records which can be accessed as all restrictive policies must be passed for each record.\u003c/p\u003e\u003cp\u003eNote that there needs to be at least one permissive policy to grant access to records before restrictive policies can be usefully used to reduce that access. If only restrictive policies exist, then no records will be accessible. When a mix of permissive and restrictive policies are present, a record is only accessible if at least one of the permissive policies passes, in addition to all the restrictive policies.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003ecommand\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe command to which the policy applies. Valid options are \u003ccode class=\"command\"\u003eALL\u003c/code\u003e, \u003ccode class=\"command\"\u003eSELECT\u003c/code\u003e, \u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e, \u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e, and \u003ccode class=\"command\"\u003eDELETE\u003c/code\u003e. \u003ccode class=\"command\"\u003eALL\u003c/code\u003e is the default. See below for specifics regarding how these are applied.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003erole_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe role(s) to which the policy is to be applied. The default is \u003ccode class=\"literal\"\u003ePUBLIC\u003c/code\u003e, which will apply the policy to all roles.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003eusing_expression\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eAny \u003cacronym\u003eSQL\u003c/acronym\u003e conditional expression (returning \u003ccode class=\"type\"\u003eboolean\u003c/code\u003e). The conditional expression cannot contain any aggregate or window functions. This expression will be added to queries that refer to the table if row-level security is enabled. Rows for which the expression returns true will be visible. Any rows for which the expression returns false or null will not be visible to the user (in a \u003ccode class=\"command\"\u003eSELECT\u003c/code\u003e), and will not be available for modification (in an \u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e or \u003ccode class=\"command\"\u003eDELETE\u003c/code\u003e). Typically, such rows are silently suppressed; no error is reported (but see \u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" title=\"Table 300. Policies Applied by Command Type\"\u003eTable 300\u003c/a\u003e for exceptions).\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003echeck_expression\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eAny \u003cacronym\u003eSQL\u003c/acronym\u003e conditional expression (returning \u003ccode class=\"type\"\u003eboolean\u003c/code\u003e). The conditional expression cannot contain any aggregate or window functions. This expression will be used in \u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e and \u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e queries against the table if row-level security is enabled. Only rows for which the expression evaluates to true will be allowed. An error will be thrown if the expression evaluates to false or null for any of the records inserted or any of the records that result from the update. Note that the \u003cem class=\"replaceable\"\u003e\u003ccode\u003echeck_expression\u003c/code\u003e\u003c/em\u003e is evaluated against the proposed new contents of the row, not the original contents.\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cdiv class=\"refsect2\"\u003e\u003ch3\u003ePer-Command Policies\u003c/h3\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eUsing \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e for a policy means that it will apply to all commands, regardless of the type of command. If an \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policy exists and more specific policies exist, then both the \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policy and the more specific policy (or policies) will be applied. Additionally, \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policies will be applied to both the selection side of a query and the modification side, using the \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expression for both cases if only a \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expression has been defined.\u003c/p\u003e\u003cp\u003eAs an example, if an \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e is issued, then the \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policy will be applicable both to what the \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e will be able to select as rows to be updated (applying the \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expression), and to the resulting updated rows, to check if they are permitted to be added to the table (applying the \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expression, if defined, and the \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expression otherwise). If an \u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e or \u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e command attempts to add rows to the table that do not pass the \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policy's \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expression (or its \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expression, if it does not have a \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expression), the entire command will be aborted.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eUsing \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e for a policy means that it will apply to \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e queries and whenever \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e permissions are required on the relation the policy is defined for. The result is that only those records from the relation that pass the \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policy will be returned during a \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e query, and that queries that require \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e permissions, such as \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e, \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e, and \u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e, will also only see those records that are allowed by the \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policy. A \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policy cannot have a \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expression, as it only applies in cases where records are being retrieved from the relation, except as described below.\u003c/p\u003e\u003cp\u003eIf a data-modifying query has a \u003ccode class=\"literal\"\u003eRETURNING\u003c/code\u003e clause, \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e permissions are required on the relation, and any newly inserted or updated rows from the relation must satisfy the relation's \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policies in order to be available to the \u003ccode class=\"literal\"\u003eRETURNING\u003c/code\u003e clause. If a newly inserted or updated row does not satisfy the relation's \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policies, an error will be thrown (inserted or updated rows to be returned are \u003cspan class=\"emphasis\"\u003e\u003cem\u003enever\u003c/em\u003e\u003c/span\u003e silently ignored).\u003c/p\u003e\u003cp\u003eIf an \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e has an \u003ccode class=\"literal\"\u003eON CONFLICT DO UPDATE\u003c/code\u003e clause, or an \u003ccode class=\"literal\"\u003eON CONFLICT DO NOTHING\u003c/code\u003e clause with an arbiter index or constraint specification, then \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e permissions are required on the relation, and the rows proposed for insertion are checked using the relation's \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policies. If a row proposed for insertion does not satisfy the relation's \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policies, an error is thrown (the \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e is \u003cspan class=\"emphasis\"\u003e\u003cem\u003enever\u003c/em\u003e\u003c/span\u003e silently avoided). In addition, if the \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e path is taken, the row to be updated and the new updated row are checked against the relation's \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policies, and an error is thrown if they are not satisfied (an auxiliary \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e is \u003cspan class=\"emphasis\"\u003e\u003cem\u003enever\u003c/em\u003e\u003c/span\u003e silently avoided).\u003c/p\u003e\u003cp\u003eA \u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e command requires \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e permissions on both the source and target relations, and so each relation's \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policies are applied before they are joined, and the \u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e actions will only see those records that are allowed by those policies. In addition, if an \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e action is executed, the target relation's \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policies are applied to the updated row, as for a standalone \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e, except that an error is thrown if they are not satisfied.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eUsing \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e for a policy means that it will apply to \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e commands and \u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e commands that contain \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e actions. Rows being inserted that do not pass this policy will result in a policy violation error, and the entire \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e command will be aborted. An \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e policy cannot have a \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expression, as it only applies in cases where records are being added to the relation.\u003c/p\u003e\u003cp\u003eNote that an \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e with an \u003ccode class=\"literal\"\u003eON CONFLICT DO NOTHING/UPDATE\u003c/code\u003e clause will check the \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e policies' \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expressions for all rows proposed for insertion, regardless of whether or not they end up being inserted.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eUsing \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e for a policy means that it will apply to \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e, \u003ccode class=\"literal\"\u003eSELECT FOR UPDATE\u003c/code\u003e, and \u003ccode class=\"literal\"\u003eSELECT FOR SHARE\u003c/code\u003e commands, as well as auxiliary \u003ccode class=\"literal\"\u003eON CONFLICT DO UPDATE\u003c/code\u003e clauses of \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e commands, and \u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e commands containing \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e actions. Since an \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e command involves pulling an existing record and replacing it with a new modified record, \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e policies accept both a \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expression and a \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expression. The \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expression determines which records the \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e command will see to operate against, while the \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expression defines which modified rows are allowed to be stored back into the relation.\u003c/p\u003e\u003cp\u003eAny rows whose updated values do not pass the \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expression will cause an error, and the entire command will be aborted. If only a \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e clause is specified, then that clause will be used for both \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e and \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e cases.\u003c/p\u003e\u003cp\u003eTypically an \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e command also needs to read data from columns in the relation being updated (e.g., in a \u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e clause or a \u003ccode class=\"literal\"\u003eRETURNING\u003c/code\u003e clause, or in an expression on the right hand side of the \u003ccode class=\"literal\"\u003eSET\u003c/code\u003e clause). In this case, \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e rights are also required on the relation being updated, and the appropriate \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e or \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policies will be applied in addition to the \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e policies. Thus the user must have access to the row(s) being updated through a \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e or \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policy in addition to being granted permission to update the row(s) via an \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e or \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policy.\u003c/p\u003e\u003cp\u003eWhen an \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e command has an auxiliary \u003ccode class=\"literal\"\u003eON CONFLICT DO UPDATE\u003c/code\u003e clause, if the \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e path is taken, the row to be updated is first checked against the \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expressions of any \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e policies, and then the new updated row is checked against the \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expressions. Note, however, that unlike a standalone \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e command, if the existing row does not pass the \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expressions, an error will be thrown (the \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e path will \u003cspan class=\"emphasis\"\u003e\u003cem\u003enever\u003c/em\u003e\u003c/span\u003e be silently avoided). The same applies to an \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e action of a \u003ccode class=\"command\"\u003eMERGE\u003c/code\u003e command.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eUsing \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e for a policy means that it will apply to \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e commands and \u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e commands containing \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e actions. For a \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e command, only rows that pass this policy will be seen by the \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e command. There can be rows that are visible through a \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policy that are not available for deletion, if they do not pass the \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e expression for the \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e policy. Note, however, that a \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e action in a \u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e command will see rows that are visible through \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e policies, and if the \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e policy does not pass for such a row, an error will be thrown.\u003c/p\u003e\u003cp\u003eIn most cases a \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e command also needs to read data from columns in the relation that it is deleting from (e.g., in a \u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e clause or a \u003ccode class=\"literal\"\u003eRETURNING\u003c/code\u003e clause). In this case, \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e rights are also required on the relation, and the appropriate \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e or \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policies will be applied in addition to the \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e policies. Thus the user must have access to the row(s) being deleted through a \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e or \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policy in addition to being granted permission to delete the row(s) via a \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e or \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policy.\u003c/p\u003e\u003cp\u003eA \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e policy cannot have a \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e expression, as it only applies in cases where records are being deleted from the relation, so that there is no new row to check.\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" title=\"Table 300. Policies Applied by Command Type\"\u003eTable 300\u003c/a\u003e summarizes how the different types of policy apply to specific commands. In the table, \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003echeck\u003c/span\u003e”\u003c/span\u003e means that the policy expression is checked and an error is thrown if it returns false or null, whereas \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003efilter\u003c/span\u003e”\u003c/span\u003e means that the row is silently ignored if the policy expression returns false or null.\u003c/p\u003e\u003cdiv class=\"table\"\u003e\u003cp class=\"title\"\u003e\u003cstrong\u003eTable 300. Policies Applied by Command Type\u003c/strong\u003e\u003c/p\u003e\u003cdiv class=\"table-contents\"\u003e\u003ctable class=\"table\"\u003e\u003cthead\u003e\u003ctr\u003e\u003cth rowspan=\"2\"\u003eCommand\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eSELECT/ALL policy\u003c/code\u003e\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eINSERT/ALL policy\u003c/code\u003e\u003c/th\u003e\u003cth colspan=\"2\"\u003e\u003ccode class=\"literal\"\u003eUPDATE/ALL policy\u003c/code\u003e\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eDELETE/ALL policy\u003c/code\u003e\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eUSING expression\u003c/code\u003e\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eWITH CHECK expression\u003c/code\u003e\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eUSING expression\u003c/code\u003e\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eWITH CHECK expression\u003c/code\u003e\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eUSING expression\u003c/code\u003e\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eSELECT\u003c/code\u003e / \u003ccode class=\"command\"\u003eCOPY ... TO\u003c/code\u003e\u003c/td\u003e\u003ctd\u003eFilter existing row\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eSELECT FOR UPDATE/SHARE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003eFilter existing row\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003eFilter existing row\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e\u003c/td\u003e\u003ctd\u003eCheck new row \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eCheck new row\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003eFilter existing row \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e \u0026amp; check new row \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003eFilter existing row\u003c/td\u003e\u003ctd\u003eCheck new row\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eDELETE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003eFilter existing row \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003eFilter existing row\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eINSERT ... ON CONFLICT\u003c/code\u003e\u003c/td\u003e\u003ctd\u003eCheck new row \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.id-1.9.3.75.6.3.4.2.5.6.2.1\"\u003e\u003csup\u003e[b]\u003c/sup\u003e\u003c/a\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-PRIV\"\u003e\u003csup\u003e[c]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eCheck new row \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-PRIV\"\u003e\u003csup\u003e[c]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eON CONFLICT DO UPDATE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003eCheck existing \u0026amp; new rows \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-UPDATE-PRIV\"\u003e\u003csup\u003e[d]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003eCheck existing row\u003c/td\u003e\u003ctd\u003eCheck new row \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-UPDATE-PRIV\"\u003e\u003csup\u003e[d]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eMERGE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003eFilter source \u0026amp; target rows\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eMERGE ... THEN INSERT\u003c/code\u003e\u003c/td\u003e\u003ctd\u003eCheck new row \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003eCheck new row\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eMERGE ... THEN UPDATE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003eCheck new row\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003eCheck existing row\u003c/td\u003e\u003ctd\u003eCheck new row\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eMERGE ... THEN DELETE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003eCheck existing row\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd colspan=\"6\"\u003e\u003cdiv class=\"footnote\"\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e If read access is required to either the existing or new row (for example, a \u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e or \u003ccode class=\"literal\"\u003eRETURNING\u003c/code\u003e clause that refers to columns from the relation).\u003c/p\u003e\u003c/div\u003e\u003cdiv class=\"footnote\"\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#id-1.9.3.75.6.3.4.2.5.6.2.1\"\u003e\u003csup\u003e[b]\u003c/sup\u003e\u003c/a\u003e If an arbiter index or constraint is specified.\u003c/p\u003e\u003c/div\u003e\u003cdiv class=\"footnote\"\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#RLS-ON-CONFLICT-PRIV\"\u003e\u003csup\u003e[c]\u003c/sup\u003e\u003c/a\u003e Row proposed for insertion is checked regardless of whether or not a conflict occurs.\u003c/p\u003e\u003c/div\u003e\u003cdiv class=\"footnote\"\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#RLS-ON-CONFLICT-UPDATE-PRIV\"\u003e\u003csup\u003e[d]\u003c/sup\u003e\u003c/a\u003e New row of the auxiliary \u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e command, which might be different from the new row of the original \u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e command.\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr\u003e\u003c/div\u003e\u003cdiv class=\"refsect2\"\u003e\u003ch3\u003eApplication of Multiple Policies\u003c/h3\u003e\u003cp\u003eWhen multiple policies of different command types apply to the same command (for example, \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e and \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e policies applied to an \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e command), then the user must have both types of permissions (for example, permission to select rows from the relation as well as permission to update them). Thus the expressions for one type of policy are combined with the expressions for the other type of policy using the \u003ccode class=\"literal\"\u003eAND\u003c/code\u003e operator.\u003c/p\u003e\u003cp\u003eWhen multiple policies of the same command type apply to the same command, then there must be at least one \u003ccode class=\"literal\"\u003ePERMISSIVE\u003c/code\u003e policy granting access to the relation, and all of the \u003ccode class=\"literal\"\u003eRESTRICTIVE\u003c/code\u003e policies must pass. Thus all the \u003ccode class=\"literal\"\u003ePERMISSIVE\u003c/code\u003e policy expressions are combined using \u003ccode class=\"literal\"\u003eOR\u003c/code\u003e, all the \u003ccode class=\"literal\"\u003eRESTRICTIVE\u003c/code\u003e policy expressions are combined using \u003ccode class=\"literal\"\u003eAND\u003c/code\u003e, and the results are combined using \u003ccode class=\"literal\"\u003eAND\u003c/code\u003e. If there are no \u003ccode class=\"literal\"\u003ePERMISSIVE\u003c/code\u003e policies, then access is denied.\u003c/p\u003e\u003cp\u003eNote that, for the purposes of combining multiple policies, \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e policies are treated as having the same type as whichever other type of policy is being applied.\u003c/p\u003e\u003cp\u003eFor example, in an \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e command requiring both \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e and \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e permissions, if there are multiple applicable policies of each type, they will be combined as follows:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e from RESTRICTIVE SELECT/ALL policy 1\nAND\n\u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e from RESTRICTIVE SELECT/ALL policy 2\nAND\n...\nAND\n(\n  \u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e from PERMISSIVE SELECT/ALL policy 1\n  OR\n  \u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e from PERMISSIVE SELECT/ALL policy 2\n  OR\n  ...\n)\nAND\n\u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e from RESTRICTIVE UPDATE/ALL policy 1\nAND\n\u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e from RESTRICTIVE UPDATE/ALL policy 2\nAND\n...\nAND\n(\n  \u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e from PERMISSIVE UPDATE/ALL policy 1\n  OR\n  \u003cem class=\"replaceable\"\u003e\u003ccode\u003eexpression\u003c/code\u003e\u003c/em\u003e from PERMISSIVE UPDATE/ALL policy 2\n  OR\n  ...\n)\n\u003c/pre\u003e\u003c/div\u003e","key":"parameters","title":"Parameters"},{"html":"\u003cp\u003eYou must be the owner of a table to create or change policies for it.\u003c/p\u003e\u003cp\u003eWhile policies will be applied for explicit queries against tables in the database, they are not applied when the system is performing internal referential integrity checks or validating constraints. This means there are indirect ways to determine that a given value exists. An example of this is attempting to insert a duplicate value into a column that is a primary key or has a unique constraint. If the insert fails then the user can infer that the value already exists. (This example assumes that the user is permitted by policy to insert records which they are not allowed to see.) Another example is where a user is allowed to insert into a table which references another, otherwise hidden table. Existence can be determined by the user inserting values into the referencing table, where success would indicate that the value exists in the referenced table. These issues can be addressed by carefully crafting policies to prevent users from being able to insert, delete, or update records at all which might possibly indicate a value they are not otherwise able to see, or by using generated values (e.g., surrogate keys) instead of keys with external meanings.\u003c/p\u003e\u003cp\u003eGenerally, the system will enforce filter conditions imposed using security policies prior to qualifications that appear in user queries, in order to prevent inadvertent exposure of the protected data to user-defined functions which might not be trustworthy. However, functions and operators marked by the system (or the system administrator) as \u003ccode class=\"literal\"\u003eLEAKPROOF\u003c/code\u003e may be evaluated before policy expressions, as they are assumed to be trustworthy.\u003c/p\u003e\u003cp\u003eSince policy expressions are added to the user's query directly, they will be run with the rights of the user running the overall query. Therefore, users who are using a given policy must be able to access any tables or functions referenced in the expression or they will simply receive a permission denied error when attempting to query the table that has row-level security enabled. This does not change how views work, however. As with normal queries and views, permission checks and policies for the tables which are referenced by a view will use the view owner's rights and any policies which apply to the view owner, except if the view is defined using the \u003ccode class=\"literal\"\u003esecurity_invoker\u003c/code\u003e option (see \u003ca href=\"/docs/18/sql-createview.html\" title=\"CREATE VIEW\"\u003e\u003ccode class=\"command\"\u003eCREATE VIEW\u003c/code\u003e\u003c/a\u003e).\u003c/p\u003e\u003cp\u003eNo separate policy exists for \u003ccode class=\"command\"\u003eMERGE\u003c/code\u003e. Instead, the policies defined for \u003ccode class=\"command\"\u003eSELECT\u003c/code\u003e, \u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e, \u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e, and \u003ccode class=\"command\"\u003eDELETE\u003c/code\u003e are applied while executing \u003ccode class=\"command\"\u003eMERGE\u003c/code\u003e, depending on the actions that are performed.\u003c/p\u003e\u003cp\u003eAdditional discussion and practical examples can be found in \u003ca href=\"/docs/18/ddl-rowsecurity.html\" title=\"5.9. Row Security Policies\"\u003eSection 5.9\u003c/a\u003e.\u003c/p\u003e","key":"notes","title":"Notes"},{"html":"\u003cp\u003e\u003ccode class=\"command\"\u003eCREATE POLICY\u003c/code\u003e is a \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e extension.\u003c/p\u003e","key":"compatibility","title":"Compatibility"},{"html":"\u003cspan class=\"simplelist\"\u003e\u003ca href=\"/wiki/sql/alter-policy/?v=18\" title=\"ALTER POLICY\"\u003e\u003cspan class=\"refentrytitle\"\u003eALTER POLICY\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/drop-policy/?v=18\" title=\"DROP POLICY\"\u003e\u003cspan class=\"refentrytitle\"\u003eDROP POLICY\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/alter-table/?v=18\" title=\"ALTER TABLE\"\u003e\u003cspan class=\"refentrytitle\"\u003eALTER TABLE\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e","key":"see_also","title":"See Also"}],"sections_same_as":"","slug":"18","synopsis_html":"CREATE POLICY \u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e ON \u003cem class=\"replaceable\"\u003e\u003ccode\u003etable_name\u003c/code\u003e\u003c/em\u003e\n    [ AS { PERMISSIVE | RESTRICTIVE } ]\n    [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]\n    [ TO { \u003cem class=\"replaceable\"\u003e\u003ccode\u003erole_name\u003c/code\u003e\u003c/em\u003e | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]\n    [ USING ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003eusing_expression\u003c/code\u003e\u003c/em\u003e ) ]\n    [ WITH CHECK ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003echeck_expression\u003c/code\u003e\u003c/em\u003e ) ]","synopsis_text":"CREATE POLICY name ON table_name\n[ AS { PERMISSIVE | RESTRICTIVE } ]\n[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]\n[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]\n[ USING ( using_expression ) ]\n[ WITH CHECK ( check_expression ) ]"},"ManualEvidence":{},"MeasuredEvidence":{}},"Text":{"Collection":"sql","Key":"create-policy","SourceDatabase":"pgweb","Version":"18","Locale":"zh-Hans","Title":"CREATE POLICY","Summary":"为一个表定义一条新的行级安全策略","BodyHTML":"\u003cpre\u003eCREATE POLICY name ON table_name\n[ AS { PERMISSIVE | RESTRICTIVE } ]\n[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]\n[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]\n[ USING ( using_expression ) ]\n[ WITH CHECK ( check_expression ) ]\u003c/pre\u003e\u003csection\u003e\u003ch2\u003e描述\u003c/h2\u003e\u003cp\u003e\u003ccode\u003eCREATE POLICY\u003c/code\u003e命令为一个表定义一条新的行级安全策略。请注意，必须先在该表上启用行级安全（使用 \u003ccode\u003eALTER TABLE ... ENABLE ROW LEVEL SECURITY\u003c/code\u003e），已创建的策略才会被应用。\u003c/p\u003e\u003cp\u003e策略允许对符合相关策略表达式的行进行选择、插入、更新或删除。现有表行会根据\u003ccode\u003eUSING\u003c/code\u003e中指定的表达式进行检查，而将通过\u003ccode\u003eINSERT\u003c/code\u003e或\u003ccode\u003eUPDATE\u003c/code\u003e创建的新行则会根据\u003ccode\u003eWITH CHECK\u003c/code\u003e中指定的表达式进行检查。当 \u003ccode\u003eUSING\u003c/code\u003e表达式对给定行返回真时，该行对用户可见；如果返回假或 null，则该行不可见。通常，当某行不可见时不会报错，但也有例外，见\u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" rel=\"nofollow\"\u003e表 300\u003c/a\u003e。当 \u003ccode\u003eWITH CHECK\u003c/code\u003e表达式对某行返回真时，该行会被插入或更新；如果返回假或 null，则会报错。\u003c/p\u003e\u003cp\u003e对于\u003ccode\u003eINSERT\u003c/code\u003e、\u003ccode\u003eUPDATE\u003c/code\u003e和 \u003ccode\u003eMERGE\u003c/code\u003e语句，\u003ccode\u003eWITH CHECK\u003c/code\u003e表达式会在\u003ccode\u003eBEFORE\u003c/code\u003e 触发器触发后、在进行任何实际数据修改之前强制执行。因此，\u003ccode\u003eBEFORE ROW\u003c/code\u003e触发器可以修改待插入的数据，从而影响安全策略检查的结果。\u003ccode\u003eWITH CHECK\u003c/code\u003e表达式会在任何其他约束之前执行。\u003c/p\u003e\u003cp\u003e策略名称按表区分。因此，同一个策略名可以用于许多不同的表，并且在每个表上都可以有适合该表的定义。\u003c/p\u003e\u003cp\u003e策略可以针对特定命令或特定角色应用。除非另有指定，新建策略默认适用于所有命令和角色。多个策略可以应用于同一命令；更多细节见下文。\u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" rel=\"nofollow\"\u003e表 300\u003c/a\u003e总结了不同类型的策略如何应用于特定命令。\u003c/p\u003e\u003cp\u003e对于既可以具有\u003ccode\u003eUSING\u003c/code\u003e又可以具有 \u003ccode\u003eWITH CHECK\u003c/code\u003e表达式的策略（\u003ccode\u003eALL\u003c/code\u003e 和\u003ccode\u003eUPDATE\u003c/code\u003e），如果未定义 \u003ccode\u003eWITH CHECK\u003c/code\u003e表达式，那么\u003ccode\u003eUSING\u003c/code\u003e 表达式将同时用于决定哪些行可见（普通\u003ccode\u003eUSING\u003c/code\u003e情形）以及允许写入哪些新行（\u003ccode\u003eWITH CHECK\u003c/code\u003e情形）。\u003c/p\u003e\u003cp\u003e如果某个表启用了行级安全，但不存在适用的策略，则会假定存在一条\u003cspan\u003e“\u003cspan\u003e默认拒绝\u003c/span\u003e”\u003c/span\u003e策略，因此没有任何行可见或可更新。\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e参数\u003c/h2\u003e\u003cdiv\u003e\u003cdl\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e要创建的策略名称。它必须不同于该表上任何其他策略的名称。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003etable_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e该策略适用的表的名称（可选模式限定）。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003ePERMISSIVE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定将该策略创建为宽松策略。适用于给定查询的所有宽松策略都会使用布尔\u003cspan\u003e“\u003cspan\u003eOR\u003c/span\u003e”\u003c/span\u003e操作符组合在一起。通过创建宽松策略，管理员可以扩大可访问行的集合。策略默认是宽松的。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eRESTRICTIVE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定将该策略创建为限制性策略。适用于给定查询的所有限制性策略都会使用布尔\u003cspan\u003e“\u003cspan\u003eAND\u003c/span\u003e”\u003c/span\u003e操作符组合在一起。通过创建限制性策略，管理员可以缩小可访问行的集合，因为每一行都必须通过所有限制性策略。\u003c/p\u003e\u003cp\u003e请注意，要让限制性策略能够有效缩小访问范围，必须先至少有一条宽松策略授予对行的访问。如果只存在限制性策略，则没有任何行可访问。当宽松策略和限制性策略混合存在时，只有在至少一条宽松策略通过且所有限制性策略也都通过时，某一行才可访问。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003ecommand\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e该策略适用的命令。有效选项是 \u003ccode\u003eALL\u003c/code\u003e、\u003ccode\u003eSELECT\u003c/code\u003e、\u003ccode\u003eINSERT\u003c/code\u003e、\u003ccode\u003eUPDATE\u003c/code\u003e 和\u003ccode\u003eDELETE\u003c/code\u003e。\u003ccode\u003eALL\u003c/code\u003e是默认值。有关这些策略如何应用的细节见下文。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003erole_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e该策略适用的角色（或多个角色）。默认是\u003ccode\u003ePUBLIC\u003c/code\u003e，即对所有角色应用该策略。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003eusing_expression\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e任意返回\u003ccode\u003eboolean\u003c/code\u003e的\u003cacronym\u003eSQL\u003c/acronym\u003e条件表达式。该条件表达式不能包含任何聚合函数或窗口函数。如果启用了行级安全，该表达式会被添加到引用该表的查询中。表达式返回真的行将对用户可见。表达式返回假或 null 的行在\u003ccode\u003eSELECT\u003c/code\u003e中对用户不可见，在\u003ccode\u003eUPDATE\u003c/code\u003e或\u003ccode\u003eDELETE\u003c/code\u003e中也不能用于修改。通常，这类行会被静默忽略，不会报告错误（但例外情况见\u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" rel=\"nofollow\"\u003e表 300\u003c/a\u003e）。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003echeck_expression\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e任意返回\u003ccode\u003eboolean\u003c/code\u003e的\u003cacronym\u003eSQL\u003c/acronym\u003e条件表达式。该条件表达式不能包含任何聚合函数或窗口函数。如果启用了行级安全，该表达式将用于针对该表的\u003ccode\u003eINSERT\u003c/code\u003e和 \u003ccode\u003eUPDATE\u003c/code\u003e查询。只有使该表达式求值为真的行才会被允许。对任何被插入的行，或更新后产生的任何行，如果该表达式求值为假或 null，就会抛出错误。请注意，\u003cem\u003e\u003ccode\u003echeck_expression\u003c/code\u003e\u003c/em\u003e 是针对该行拟写入的新内容而不是原始内容求值的。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e针对每种命令的策略\u003c/h3\u003e\u003cdiv\u003e\u003cdl\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eALL\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e对策略使用\u003ccode\u003eALL\u003c/code\u003e意味着无论命令类型如何，该策略都适用于所有命令。如果存在\u003ccode\u003eALL\u003c/code\u003e策略且还存在更具体的策略，则\u003ccode\u003eALL\u003c/code\u003e策略和更具体的策略（或多个策略）都会被应用。此外，\u003ccode\u003eALL\u003c/code\u003e策略会同时应用于查询的选择端和修改端，并在两端使用\u003ccode\u003eUSING\u003c/code\u003e表达式（如果只定义了\u003ccode\u003eUSING\u003c/code\u003e表达式）。\u003c/p\u003e\u003cp\u003e例如，如果发出\u003ccode\u003eUPDATE\u003c/code\u003e，那么\u003ccode\u003eALL\u003c/code\u003e 策略既适用于\u003ccode\u003eUPDATE\u003c/code\u003e能够选出作为更新目标的行（应用\u003ccode\u003eUSING\u003c/code\u003e表达式），也适用于更新后的结果行，以检查它们是否允许被写入该表（若定义了 \u003ccode\u003eWITH CHECK\u003c/code\u003e表达式则应用之，否则应用 \u003ccode\u003eUSING\u003c/code\u003e表达式）。如果\u003ccode\u003eINSERT\u003c/code\u003e 或\u003ccode\u003eUPDATE\u003c/code\u003e命令试图向表中添加未通过 \u003ccode\u003eALL\u003c/code\u003e策略的\u003ccode\u003eWITH CHECK\u003c/code\u003e 表达式（若未定义\u003ccode\u003eWITH CHECK\u003c/code\u003e表达式，则为其 \u003ccode\u003eUSING\u003c/code\u003e表达式）的行，整个命令将被中止。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eSELECT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e对策略使用\u003ccode\u003eSELECT\u003c/code\u003e，意味着它适用于 \u003ccode\u003eSELECT\u003c/code\u003e查询，以及在其定义所在关系上需要 \u003ccode\u003eSELECT\u003c/code\u003e权限的任何场景。结果是，只有通过 \u003ccode\u003eSELECT\u003c/code\u003e策略的那些行才会在 \u003ccode\u003eSELECT\u003c/code\u003e查询中返回，而像\u003ccode\u003eUPDATE\u003c/code\u003e、\u003ccode\u003eDELETE\u003c/code\u003e和\u003ccode\u003eMERGE\u003c/code\u003e这类需要 \u003ccode\u003eSELECT\u003c/code\u003e权限的查询，也只能看到 \u003ccode\u003eSELECT\u003c/code\u003e策略允许的那些行。\u003ccode\u003eSELECT\u003c/code\u003e策略不能带有 \u003ccode\u003eWITH CHECK\u003c/code\u003e表达式，因为它只适用于从关系中取回行的情况，下述情形除外。\u003c/p\u003e\u003cp\u003e如果某个修改数据的查询带有\u003ccode\u003eRETURNING\u003c/code\u003e子句，则该关系上需要\u003ccode\u003eSELECT\u003c/code\u003e权限，并且该关系中新插入或更新的任何行都必须满足该关系的\u003ccode\u003eSELECT\u003c/code\u003e策略，才能提供给 \u003ccode\u003eRETURNING\u003c/code\u003e子句。如果新插入或更新的行不满足该关系的 \u003ccode\u003eSELECT\u003c/code\u003e策略，就会抛出错误（需要返回的插入或更新行\u003cspan\u003e\u003cem\u003e绝不会\u003c/em\u003e\u003c/span\u003e被静默忽略）。\u003c/p\u003e\u003cp\u003e如果\u003ccode\u003eINSERT\u003c/code\u003e带有\u003ccode\u003eON CONFLICT DO UPDATE\u003c/code\u003e子句，或带有指定仲裁索引或约束的\u003ccode\u003eON CONFLICT DO NOTHING\u003c/code\u003e子句，那么该关系上也需要\u003ccode\u003eSELECT\u003c/code\u003e权限，并且提议插入的行会按照该关系的 \u003ccode\u003eSELECT\u003c/code\u003e策略进行检查。如果某个提议插入的行不满足该关系的 \u003ccode\u003eSELECT\u003c/code\u003e策略，就会抛出错误（\u003ccode\u003eINSERT\u003c/code\u003e\u003cspan\u003e\u003cem\u003e绝不会\u003c/em\u003e\u003c/span\u003e被静默跳过）。此外，如果走的是\u003ccode\u003eUPDATE\u003c/code\u003e路径，则待更新的行以及更新后的新行都会按照该关系的\u003ccode\u003eSELECT\u003c/code\u003e策略进行检查；如果不满足，同样会报错（辅助的\u003ccode\u003eUPDATE\u003c/code\u003e\u003cspan\u003e\u003cem\u003e绝不会\u003c/em\u003e\u003c/span\u003e被静默跳过）。\u003c/p\u003e\u003cp\u003e\u003ccode\u003eMERGE\u003c/code\u003e命令要求在源关系和目标关系上都具有 \u003ccode\u003eSELECT\u003c/code\u003e权限，因此每个关系的\u003ccode\u003eSELECT\u003c/code\u003e策略都会在连接它们之前被应用，而\u003ccode\u003eMERGE\u003c/code\u003e动作也只能看到这些策略允许的行。另外，如果执行了\u003ccode\u003eUPDATE\u003c/code\u003e动作，则目标关系的 \u003ccode\u003eSELECT\u003c/code\u003e策略会像独立的\u003ccode\u003eUPDATE\u003c/code\u003e那样应用到更新后的行，但不同之处在于，不满足这些策略时会报错。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eINSERT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e对策略使用\u003ccode\u003eINSERT\u003c/code\u003e，意味着它将适用于 \u003ccode\u003eINSERT\u003c/code\u003e命令，以及包含\u003ccode\u003eINSERT\u003c/code\u003e动作的 \u003ccode\u003eMERGE\u003c/code\u003e命令。插入的行如果未通过该策略，将导致策略违规错误，并且整个\u003ccode\u003eINSERT\u003c/code\u003e命令将被中止。\u003ccode\u003eINSERT\u003c/code\u003e策略不能带有 \u003ccode\u003eUSING\u003c/code\u003e表达式，因为它只适用于向关系添加行的情况。\u003c/p\u003e\u003cp\u003e注意，带有\u003ccode\u003eON CONFLICT DO NOTHING/UPDATE\u003c/code\u003e子句的 \u003ccode\u003eINSERT\u003c/code\u003e，会对所有提议插入的行检查 \u003ccode\u003eINSERT\u003c/code\u003e策略的\u003ccode\u003eWITH CHECK\u003c/code\u003e表达式，无论这些行最终是否真的被插入。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eUPDATE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e对策略使用\u003ccode\u003eUPDATE\u003c/code\u003e，意味着它将适用于 \u003ccode\u003eUPDATE\u003c/code\u003e、\u003ccode\u003eSELECT FOR UPDATE\u003c/code\u003e、\u003ccode\u003eSELECT FOR SHARE\u003c/code\u003e命令，以及\u003ccode\u003eINSERT\u003c/code\u003e命令中辅助的\u003ccode\u003eON CONFLICT DO UPDATE\u003c/code\u003e子句，还适用于包含 \u003ccode\u003eUPDATE\u003c/code\u003e动作的\u003ccode\u003eMERGE\u003c/code\u003e命令。由于\u003ccode\u003eUPDATE\u003c/code\u003e命令需要取出现有行并用修改后的新行替换它，因此\u003ccode\u003eUPDATE\u003c/code\u003e策略同时接受 \u003ccode\u003eUSING\u003c/code\u003e表达式和 \u003ccode\u003eWITH CHECK\u003c/code\u003e表达式。\u003ccode\u003eUSING\u003c/code\u003e表达式决定\u003ccode\u003eUPDATE\u003c/code\u003e 命令能够看到哪些行来执行操作，而 \u003ccode\u003eWITH CHECK\u003c/code\u003e表达式则定义哪些修改后的行允许被写回该关系。\u003c/p\u003e\u003cp\u003e任何更新后的值未通过\u003ccode\u003eWITH CHECK\u003c/code\u003e表达式的行都会导致错误，并且整个命令将被中止。如果只指定了一个 \u003ccode\u003eUSING\u003c/code\u003e子句，那么该子句将被用于 \u003ccode\u003eUSING\u003c/code\u003e和\u003ccode\u003eWITH CHECK\u003c/code\u003e两种情况。\u003c/p\u003e\u003cp\u003e通常，\u003ccode\u003eUPDATE\u003c/code\u003e命令还需要从待更新关系的列中读取数据（例如在\u003ccode\u003eWHERE\u003c/code\u003e子句、\u003ccode\u003eRETURNING\u003c/code\u003e子句，或\u003ccode\u003eSET\u003c/code\u003e 子句右侧的表达式中）。这种情况下，正在被更新的关系上也需要 \u003ccode\u003eSELECT\u003c/code\u003e权限，并且除了 \u003ccode\u003eUPDATE\u003c/code\u003e策略外，还会应用适当的 \u003ccode\u003eSELECT\u003c/code\u003e或\u003ccode\u003eALL\u003c/code\u003e策略。这样，用户除了必须通过\u003ccode\u003eUPDATE\u003c/code\u003e或 \u003ccode\u003eALL\u003c/code\u003e策略获准更新这些行之外，还必须通过 \u003ccode\u003eSELECT\u003c/code\u003e或\u003ccode\u003eALL\u003c/code\u003e策略访问正在被更新的行。\u003c/p\u003e\u003cp\u003e当\u003ccode\u003eINSERT\u003c/code\u003e命令带有辅助的 \u003ccode\u003eON CONFLICT DO UPDATE\u003c/code\u003e子句时，如果走 \u003ccode\u003eUPDATE\u003c/code\u003e路径，则待更新的行会先根据各适用的\u003ccode\u003eUPDATE\u003c/code\u003e策略的\u003ccode\u003eUSING\u003c/code\u003e表达式进行检查，然后新的更新后行会再根据\u003ccode\u003eWITH CHECK\u003c/code\u003e表达式进行检查。但要注意，与独立的\u003ccode\u003eUPDATE\u003c/code\u003e命令不同，如果现有行没有通过 \u003ccode\u003eUSING\u003c/code\u003e表达式检查，就会报错（\u003ccode\u003eUPDATE\u003c/code\u003e路径\u003cspan\u003e\u003cem\u003e绝不会\u003c/em\u003e\u003c/span\u003e被静默跳过）。对\u003ccode\u003eMERGE\u003c/code\u003e命令中的\u003ccode\u003eUPDATE\u003c/code\u003e动作也是如此。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eDELETE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e对策略使用\u003ccode\u003eDELETE\u003c/code\u003e，意味着它将适用于 \u003ccode\u003eDELETE\u003c/code\u003e命令，以及包含\u003ccode\u003eDELETE\u003c/code\u003e动作的 \u003ccode\u003eMERGE\u003c/code\u003e命令。对于\u003ccode\u003eDELETE\u003c/code\u003e命令，只有通过该策略的行才会被\u003ccode\u003eDELETE\u003c/code\u003e命令看到。可能存在一些通过\u003ccode\u003eSELECT\u003c/code\u003e策略可见，但由于未通过 \u003ccode\u003eDELETE\u003c/code\u003e策略的\u003ccode\u003eUSING\u003c/code\u003e表达式而不能删除的行。但请注意，在\u003ccode\u003eMERGE\u003c/code\u003e命令中的\u003ccode\u003eDELETE\u003c/code\u003e动作会看到通过\u003ccode\u003eSELECT\u003c/code\u003e策略可见的行；如果某一行未通过 \u003ccode\u003eDELETE\u003c/code\u003e策略，就会报错。\u003c/p\u003e\u003cp\u003e在多数情况下，\u003ccode\u003eDELETE\u003c/code\u003e命令也需要从其删除所针对的关系中的列读取数据（例如在\u003ccode\u003eWHERE\u003c/code\u003e子句或 \u003ccode\u003eRETURNING\u003c/code\u003e子句中）。这种情况下，该关系上也需要\u003ccode\u003eSELECT\u003c/code\u003e权限，并且除了 \u003ccode\u003eDELETE\u003c/code\u003e策略外，还会应用适当的 \u003ccode\u003eSELECT\u003c/code\u003e或\u003ccode\u003eALL\u003c/code\u003e策略。这样，用户除了必须通过\u003ccode\u003eDELETE\u003c/code\u003e或 \u003ccode\u003eALL\u003c/code\u003e策略获准删除这些行之外，还必须通过 \u003ccode\u003eSELECT\u003c/code\u003e或\u003ccode\u003eALL\u003c/code\u003e策略访问正在被删除的行。\u003c/p\u003e\u003cp\u003e\u003ccode\u003eDELETE\u003c/code\u003e策略不能具有\u003ccode\u003eWITH CHECK\u003c/code\u003e表达式，因为它只适用于正在从关系中删除行的情况，所以没有新行需要检查。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" rel=\"nofollow\"\u003e表 300\u003c/a\u003e总结了不同类型的策略如何应用到特定命令上。在该表中，\u003cspan\u003e“\u003cspan\u003e检查\u003c/span\u003e”\u003c/span\u003e表示要检查策略表达式，若其返回假或 null 则抛出错误；而\u003cspan\u003e“\u003cspan\u003e筛选\u003c/span\u003e”\u003c/span\u003e表示若策略表达式返回假或 null，则该行会被静默忽略。\u003c/p\u003e\u003cdiv\u003e\u003cp\u003e\u003cstrong\u003e表 300. 按命令类型应用的策略\u003c/strong\u003e\u003c/p\u003e\u003cdiv\u003e\u003ctable\u003e\u003cthead\u003e\u003ctr\u003e\u003cth rowspan=\"2\"\u003e命令\u003c/th\u003e\u003cth\u003e\u003ccode\u003eSELECT/ALL策略\u003c/code\u003e\u003c/th\u003e\u003cth\u003e\u003ccode\u003eINSERT/ALL策略\u003c/code\u003e\u003c/th\u003e\u003cth colspan=\"2\"\u003e\u003ccode\u003eUPDATE/ALL策略\u003c/code\u003e\u003c/th\u003e\u003cth\u003e\u003ccode\u003eDELETE/ALL策略\u003c/code\u003e\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth\u003e\u003ccode\u003eUSING\u003c/code\u003e 表达式\u003c/th\u003e\u003cth\u003e\u003ccode\u003eWITH CHECK\u003c/code\u003e 表达式\u003c/th\u003e\u003cth\u003e\u003ccode\u003eUSING\u003c/code\u003e 表达式\u003c/th\u003e\u003cth\u003e\u003ccode\u003eWITH CHECK\u003c/code\u003e 表达式\u003c/th\u003e\u003cth\u003e\u003ccode\u003eUSING\u003c/code\u003e 表达式\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode\u003eSELECT\u003c/code\u003e / \u003ccode\u003eCOPY ... TO\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e筛选现有行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode\u003eSELECT FOR UPDATE/SHARE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e筛选现有行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e筛选现有行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode\u003eINSERT\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e检查新行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode\u003eUPDATE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e筛选现有行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e并检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e筛选现有行\u003c/td\u003e\u003ctd\u003e检查新行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode\u003eDELETE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e筛选现有行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e筛选现有行\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode\u003eINSERT ... ON CONFLICT\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.id-1.9.3.75.6.3.4.2.5.6.2.1\" rel=\"nofollow\"\u003e\u003csup\u003e[b]\u003c/sup\u003e\u003c/a\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[c]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[c]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode\u003eON CONFLICT DO UPDATE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e检查现有行和新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-UPDATE-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[d]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e检查现有行\u003c/td\u003e\u003ctd\u003e检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-UPDATE-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[d]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode\u003eMERGE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e筛选源行和目标行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode\u003eMERGE ... THEN INSERT\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e检查新行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode\u003eMERGE ... THEN UPDATE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e检查新行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e检查现有行\u003c/td\u003e\u003ctd\u003e检查新行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode\u003eMERGE ... THEN DELETE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e检查现有行\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd colspan=\"6\"\u003e\u003cdiv\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#RLS-SELECT-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e 如果需要读取现有行或新行，例如在 \u003ccode\u003eWHERE\u003c/code\u003e 或 \u003ccode\u003eRETURNING\u003c/code\u003e 子句引用该关系的列时。\u003c/p\u003e\u003c/div\u003e\u003cdiv\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#id-1.9.3.75.6.3.4.2.5.6.2.1\" rel=\"nofollow\"\u003e\u003csup\u003e[b]\u003c/sup\u003e\u003c/a\u003e 如果指定了仲裁索引或约束。\u003c/p\u003e\u003c/div\u003e\u003cdiv\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#RLS-ON-CONFLICT-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[c]\u003c/sup\u003e\u003c/a\u003e 无论最终是否实际发生冲突，提议插入的行都会被检查。\u003c/p\u003e\u003c/div\u003e\u003cdiv\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#RLS-ON-CONFLICT-UPDATE-PRIV\" rel=\"nofollow\"\u003e\u003csup\u003e[d]\u003c/sup\u003e\u003c/a\u003e 指辅助\u003ccode\u003eUPDATE\u003c/code\u003e命令中的新行，它可能与原始 \u003ccode\u003eINSERT\u003c/code\u003e命令中的新行不同。\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e多条策略的应用\u003c/h3\u003e\u003cp\u003e当不同命令类型的多条策略应用于同一命令时（例如 \u003ccode\u003eSELECT\u003c/code\u003e和\u003ccode\u003eUPDATE\u003c/code\u003e策略应用于 \u003ccode\u003eUPDATE\u003c/code\u003e命令），用户必须同时具有这两种权限（例如既有从该关系中选取行的权限，也有更新这些行的权限）。因此，一种策略类型的表达式会与另一种策略类型的表达式使用 \u003ccode\u003eAND\u003c/code\u003e操作符组合。\u003c/p\u003e\u003cp\u003e当同一命令类型的多条策略应用于同一命令时，必须至少有一条 \u003ccode\u003ePERMISSIVE\u003c/code\u003e策略授予对该关系的访问权，并且所有 \u003ccode\u003eRESTRICTIVE\u003c/code\u003e策略都必须通过。因此，所有 \u003ccode\u003ePERMISSIVE\u003c/code\u003e策略表达式使用\u003ccode\u003eOR\u003c/code\u003e 组合，所有\u003ccode\u003eRESTRICTIVE\u003c/code\u003e策略表达式使用 \u003ccode\u003eAND\u003c/code\u003e组合，然后再将两者的结果使用 \u003ccode\u003eAND\u003c/code\u003e组合。如果没有 \u003ccode\u003ePERMISSIVE\u003c/code\u003e策略，则访问被拒绝。\u003c/p\u003e\u003cp\u003e请注意，就组合多条策略而言，\u003ccode\u003eALL\u003c/code\u003e策略会被视为与当前正在应用的其他策略同一类型。\u003c/p\u003e\u003cp\u003e例如，对于一个同时需要\u003ccode\u003eSELECT\u003c/code\u003e和 \u003ccode\u003eUPDATE\u003c/code\u003e权限的\u003ccode\u003eUPDATE\u003c/code\u003e命令，如果这两类策略各自都有多个适用项，它们会按以下方式组合：\u003c/p\u003e\u003cpre\u003eRESTRICTIVE SELECT/ALL 策略 1 中的 \u003cem\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\nAND\nRESTRICTIVE SELECT/ALL 策略 2 中的 \u003cem\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\nAND\n...\nAND\n(\n  PERMISSIVE SELECT/ALL 策略 1 中的 \u003cem\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\n  OR\n  PERMISSIVE SELECT/ALL 策略 2 中的 \u003cem\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\n  OR\n  ...\n)\nAND\nRESTRICTIVE UPDATE/ALL 策略 1 中的 \u003cem\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\nAND\nRESTRICTIVE UPDATE/ALL 策略 2 中的 \u003cem\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\nAND\n...\nAND\n(\n  PERMISSIVE UPDATE/ALL 策略 1 中的 \u003cem\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\n  OR\n  PERMISSIVE UPDATE/ALL 策略 2 中的 \u003cem\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\n  OR\n  ...\n)\n\u003c/pre\u003e\u003c/div\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e注解\u003c/h2\u003e\u003cp\u003e要为一个表创建或修改策略，你必须是该表的拥有者。\u003c/p\u003e\u003cp\u003e虽然策略会应用于针对数据库中表的显式查询，但当系统执行内部引用完整性检查或验证约束时，并不会应用这些策略。这意味着仍然存在间接判断某个给定值是否存在的方法。一个例子是，尝试向某个主键列或带有唯一约束的列插入重复值。如果插入失败，用户就能推断该值已经存在。（这个例子假定策略允许该用户插入自己无权看见的行。）另一个例子是，用户被允许向一个引用了另一张表的表中插入数据，而被引用的那张表本身对其是隐藏的。用户可以通过向引用表插入值来判断其存在性；插入成功就表示该值存在于被引用表中。要解决这些问题，可以仔细设计策略，防止用户插入、删除或更新那些可能暗示其本来无权看见的值是否存在的行，或者改用生成的值（例如代理键）来代替具有外部含义的键。\u003c/p\u003e\u003cp\u003e通常，为了防止受保护的数据无意间暴露给可能不可信的用户定义函数，系统会在应用用户查询中出现的条件之前，先强制执行安全策略施加的过滤条件。不过，被系统（或系统管理员）标记为 \u003ccode\u003eLEAKPROOF\u003c/code\u003e的函数和操作符由于被假定为可信，可以在策略表达式之前求值。\u003c/p\u003e\u003cp\u003e由于策略表达式会被直接添加到用户查询中，因此它们将以执行整个查询的用户权限运行。因此，使用某条策略的用户必须能够访问表达式中引用的所有表或函数，否则在尝试查询启用了行级安全的表时，只会收到权限被拒绝的错误。不过，这并不改变视图的工作方式。与普通查询和视图一样，被视图引用的表的权限检查和策略将使用视图所有者的权限，以及适用于视图所有者的任何策略；但如果视图是用 \u003ccode\u003esecurity_invoker\u003c/code\u003e选项定义的，则例外（见 \u003ca href=\"/docs/18/sql-createview.html\" title=\"CREATE VIEW\" rel=\"nofollow\"\u003e\u003ccode\u003eCREATE VIEW\u003c/code\u003e\u003c/a\u003e）。\u003c/p\u003e\u003cp\u003e对于\u003ccode\u003eMERGE\u003c/code\u003e，不存在单独的策略。相反，执行 \u003ccode\u003eMERGE\u003c/code\u003e时会根据实际执行的动作，应用为 \u003ccode\u003eSELECT\u003c/code\u003e、\u003ccode\u003eINSERT\u003c/code\u003e、\u003ccode\u003eUPDATE\u003c/code\u003e和\u003ccode\u003eDELETE\u003c/code\u003e定义的策略。\u003c/p\u003e\u003cp\u003e更多讨论和实际示例见\u003ca href=\"/docs/18/ddl-rowsecurity.html\" rel=\"nofollow\"\u003e第 5.9 节\u003c/a\u003e。\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e兼容性\u003c/h2\u003e\u003cp\u003e\u003ccode\u003eCREATE POLICY\u003c/code\u003e是一种\u003cspan\u003ePostgreSQL\u003c/span\u003e扩展。\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e另见\u003c/h2\u003e\u003cspan\u003e\u003ca href=\"/wiki/sql/alter-policy/?v=18\" title=\"ALTER POLICY\" rel=\"nofollow\"\u003e\u003cspan\u003eALTER POLICY\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/drop-policy/?v=18\" title=\"DROP POLICY\" rel=\"nofollow\"\u003e\u003cspan\u003eDROP POLICY\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/alter-table/?v=18\" title=\"ALTER TABLE\" rel=\"nofollow\"\u003e\u003cspan\u003eALTER TABLE\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003c/section\u003e","SourceRevision":"1b5ca64c","ContentHash":"166e3edd4668fee6bd943c22d565748d350aec9b398b76091efe0fae59923dfe","Payload":{"purpose_zh":"为一个表定义一条新的行级安全策略","sections":[{"html":"\u003cp\u003e\u003ccode class=\"command\"\u003eCREATE POLICY\u003c/code\u003e命令为一个表定义一条新的行级安全策略。请注意，必须先在该表上启用行级安全（使用 \u003ccode class=\"command\"\u003eALTER TABLE ... ENABLE ROW LEVEL SECURITY\u003c/code\u003e），已创建的策略才会被应用。\u003c/p\u003e\u003cp\u003e策略允许对符合相关策略表达式的行进行选择、插入、更新或删除。现有表行会根据\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e中指定的表达式进行检查，而将通过\u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e或\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e创建的新行则会根据\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e中指定的表达式进行检查。当 \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式对给定行返回真时，该行对用户可见；如果返回假或 null，则该行不可见。通常，当某行不可见时不会报错，但也有例外，见\u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" title=\"表 300. 按命令类型应用的策略\"\u003e表 300\u003c/a\u003e。当 \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式对某行返回真时，该行会被插入或更新；如果返回假或 null，则会报错。\u003c/p\u003e\u003cp\u003e对于\u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e、\u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e和 \u003ccode class=\"command\"\u003eMERGE\u003c/code\u003e语句，\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式会在\u003ccode class=\"literal\"\u003eBEFORE\u003c/code\u003e 触发器触发后、在进行任何实际数据修改之前强制执行。因此，\u003ccode class=\"literal\"\u003eBEFORE ROW\u003c/code\u003e触发器可以修改待插入的数据，从而影响安全策略检查的结果。\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式会在任何其他约束之前执行。\u003c/p\u003e\u003cp\u003e策略名称按表区分。因此，同一个策略名可以用于许多不同的表，并且在每个表上都可以有适合该表的定义。\u003c/p\u003e\u003cp\u003e策略可以针对特定命令或特定角色应用。除非另有指定，新建策略默认适用于所有命令和角色。多个策略可以应用于同一命令；更多细节见下文。\u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" title=\"表 300. 按命令类型应用的策略\"\u003e表 300\u003c/a\u003e总结了不同类型的策略如何应用于特定命令。\u003c/p\u003e\u003cp\u003e对于既可以具有\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e又可以具有 \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式的策略（\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e 和\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e），如果未定义 \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式，那么\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e 表达式将同时用于决定哪些行可见（普通\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e情形）以及允许写入哪些新行（\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e情形）。\u003c/p\u003e\u003cp\u003e如果某个表启用了行级安全，但不存在适用的策略，则会假定存在一条\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e默认拒绝\u003c/span\u003e”\u003c/span\u003e策略，因此没有任何行可见或可更新。\u003c/p\u003e","key":"description","title":"描述"},{"html":"\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e要创建的策略名称。它必须不同于该表上任何其他策略的名称。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003etable_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e该策略适用的表的名称（可选模式限定）。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003ePERMISSIVE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定将该策略创建为宽松策略。适用于给定查询的所有宽松策略都会使用布尔\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003eOR\u003c/span\u003e”\u003c/span\u003e操作符组合在一起。通过创建宽松策略，管理员可以扩大可访问行的集合。策略默认是宽松的。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eRESTRICTIVE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e指定将该策略创建为限制性策略。适用于给定查询的所有限制性策略都会使用布尔\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003eAND\u003c/span\u003e”\u003c/span\u003e操作符组合在一起。通过创建限制性策略，管理员可以缩小可访问行的集合，因为每一行都必须通过所有限制性策略。\u003c/p\u003e\u003cp\u003e请注意，要让限制性策略能够有效缩小访问范围，必须先至少有一条宽松策略授予对行的访问。如果只存在限制性策略，则没有任何行可访问。当宽松策略和限制性策略混合存在时，只有在至少一条宽松策略通过且所有限制性策略也都通过时，某一行才可访问。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003ecommand\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e该策略适用的命令。有效选项是 \u003ccode class=\"command\"\u003eALL\u003c/code\u003e、\u003ccode class=\"command\"\u003eSELECT\u003c/code\u003e、\u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e、\u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e 和\u003ccode class=\"command\"\u003eDELETE\u003c/code\u003e。\u003ccode class=\"command\"\u003eALL\u003c/code\u003e是默认值。有关这些策略如何应用的细节见下文。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003erole_name\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e该策略适用的角色（或多个角色）。默认是\u003ccode class=\"literal\"\u003ePUBLIC\u003c/code\u003e，即对所有角色应用该策略。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003eusing_expression\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e任意返回\u003ccode class=\"type\"\u003eboolean\u003c/code\u003e的\u003cacronym\u003eSQL\u003c/acronym\u003e条件表达式。该条件表达式不能包含任何聚合函数或窗口函数。如果启用了行级安全，该表达式会被添加到引用该表的查询中。表达式返回真的行将对用户可见。表达式返回假或 null 的行在\u003ccode class=\"command\"\u003eSELECT\u003c/code\u003e中对用户不可见，在\u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e或\u003ccode class=\"command\"\u003eDELETE\u003c/code\u003e中也不能用于修改。通常，这类行会被静默忽略，不会报告错误（但例外情况见\u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" title=\"表 300. 按命令类型应用的策略\"\u003e表 300\u003c/a\u003e）。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003echeck_expression\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e任意返回\u003ccode class=\"type\"\u003eboolean\u003c/code\u003e的\u003cacronym\u003eSQL\u003c/acronym\u003e条件表达式。该条件表达式不能包含任何聚合函数或窗口函数。如果启用了行级安全，该表达式将用于针对该表的\u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e和 \u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e查询。只有使该表达式求值为真的行才会被允许。对任何被插入的行，或更新后产生的任何行，如果该表达式求值为假或 null，就会抛出错误。请注意，\u003cem class=\"replaceable\"\u003e\u003ccode\u003echeck_expression\u003c/code\u003e\u003c/em\u003e 是针对该行拟写入的新内容而不是原始内容求值的。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cdiv class=\"refsect2\"\u003e\u003ch3\u003e针对每种命令的策略\u003c/h3\u003e\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e对策略使用\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e意味着无论命令类型如何，该策略都适用于所有命令。如果存在\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e策略且还存在更具体的策略，则\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e策略和更具体的策略（或多个策略）都会被应用。此外，\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e策略会同时应用于查询的选择端和修改端，并在两端使用\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式（如果只定义了\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式）。\u003c/p\u003e\u003cp\u003e例如，如果发出\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e，那么\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e 策略既适用于\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e能够选出作为更新目标的行（应用\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式），也适用于更新后的结果行，以检查它们是否允许被写入该表（若定义了 \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式则应用之，否则应用 \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式）。如果\u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e 或\u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e命令试图向表中添加未通过 \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e策略的\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e 表达式（若未定义\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式，则为其 \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式）的行，整个命令将被中止。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e对策略使用\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e，意味着它适用于 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e查询，以及在其定义所在关系上需要 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e权限的任何场景。结果是，只有通过 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略的那些行才会在 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e查询中返回，而像\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e、\u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e和\u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e这类需要 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e权限的查询，也只能看到 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略允许的那些行。\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略不能带有 \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式，因为它只适用于从关系中取回行的情况，下述情形除外。\u003c/p\u003e\u003cp\u003e如果某个修改数据的查询带有\u003ccode class=\"literal\"\u003eRETURNING\u003c/code\u003e子句，则该关系上需要\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e权限，并且该关系中新插入或更新的任何行都必须满足该关系的\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略，才能提供给 \u003ccode class=\"literal\"\u003eRETURNING\u003c/code\u003e子句。如果新插入或更新的行不满足该关系的 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略，就会抛出错误（需要返回的插入或更新行\u003cspan class=\"emphasis\"\u003e\u003cem\u003e绝不会\u003c/em\u003e\u003c/span\u003e被静默忽略）。\u003c/p\u003e\u003cp\u003e如果\u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e带有\u003ccode class=\"literal\"\u003eON CONFLICT DO UPDATE\u003c/code\u003e子句，或带有指定仲裁索引或约束的\u003ccode class=\"literal\"\u003eON CONFLICT DO NOTHING\u003c/code\u003e子句，那么该关系上也需要\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e权限，并且提议插入的行会按照该关系的 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略进行检查。如果某个提议插入的行不满足该关系的 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略，就会抛出错误（\u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e\u003cspan class=\"emphasis\"\u003e\u003cem\u003e绝不会\u003c/em\u003e\u003c/span\u003e被静默跳过）。此外，如果走的是\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e路径，则待更新的行以及更新后的新行都会按照该关系的\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略进行检查；如果不满足，同样会报错（辅助的\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e\u003cspan class=\"emphasis\"\u003e\u003cem\u003e绝不会\u003c/em\u003e\u003c/span\u003e被静默跳过）。\u003c/p\u003e\u003cp\u003e\u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e命令要求在源关系和目标关系上都具有 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e权限，因此每个关系的\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略都会在连接它们之前被应用，而\u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e动作也只能看到这些策略允许的行。另外，如果执行了\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e动作，则目标关系的 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略会像独立的\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e那样应用到更新后的行，但不同之处在于，不满足这些策略时会报错。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e对策略使用\u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e，意味着它将适用于 \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e命令，以及包含\u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e动作的 \u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e命令。插入的行如果未通过该策略，将导致策略违规错误，并且整个\u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e命令将被中止。\u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e策略不能带有 \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式，因为它只适用于向关系添加行的情况。\u003c/p\u003e\u003cp\u003e注意，带有\u003ccode class=\"literal\"\u003eON CONFLICT DO NOTHING/UPDATE\u003c/code\u003e子句的 \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e，会对所有提议插入的行检查 \u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e策略的\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式，无论这些行最终是否真的被插入。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e对策略使用\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e，意味着它将适用于 \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e、\u003ccode class=\"literal\"\u003eSELECT FOR UPDATE\u003c/code\u003e、\u003ccode class=\"literal\"\u003eSELECT FOR SHARE\u003c/code\u003e命令，以及\u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e命令中辅助的\u003ccode class=\"literal\"\u003eON CONFLICT DO UPDATE\u003c/code\u003e子句，还适用于包含 \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e动作的\u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e命令。由于\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e命令需要取出现有行并用修改后的新行替换它，因此\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e策略同时接受 \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式和 \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式。\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式决定\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e 命令能够看到哪些行来执行操作，而 \u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式则定义哪些修改后的行允许被写回该关系。\u003c/p\u003e\u003cp\u003e任何更新后的值未通过\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式的行都会导致错误，并且整个命令将被中止。如果只指定了一个 \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e子句，那么该子句将被用于 \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e和\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e两种情况。\u003c/p\u003e\u003cp\u003e通常，\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e命令还需要从待更新关系的列中读取数据（例如在\u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e子句、\u003ccode class=\"literal\"\u003eRETURNING\u003c/code\u003e子句，或\u003ccode class=\"literal\"\u003eSET\u003c/code\u003e 子句右侧的表达式中）。这种情况下，正在被更新的关系上也需要 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e权限，并且除了 \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e策略外，还会应用适当的 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e或\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e策略。这样，用户除了必须通过\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e或 \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e策略获准更新这些行之外，还必须通过 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e或\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e策略访问正在被更新的行。\u003c/p\u003e\u003cp\u003e当\u003ccode class=\"literal\"\u003eINSERT\u003c/code\u003e命令带有辅助的 \u003ccode class=\"literal\"\u003eON CONFLICT DO UPDATE\u003c/code\u003e子句时，如果走 \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e路径，则待更新的行会先根据各适用的\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e策略的\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式进行检查，然后新的更新后行会再根据\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式进行检查。但要注意，与独立的\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e命令不同，如果现有行没有通过 \u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式检查，就会报错（\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e路径\u003cspan class=\"emphasis\"\u003e\u003cem\u003e绝不会\u003c/em\u003e\u003c/span\u003e被静默跳过）。对\u003ccode class=\"command\"\u003eMERGE\u003c/code\u003e命令中的\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e动作也是如此。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e对策略使用\u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e，意味着它将适用于 \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e命令，以及包含\u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e动作的 \u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e命令。对于\u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e命令，只有通过该策略的行才会被\u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e命令看到。可能存在一些通过\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略可见，但由于未通过 \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e策略的\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e表达式而不能删除的行。但请注意，在\u003ccode class=\"literal\"\u003eMERGE\u003c/code\u003e命令中的\u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e动作会看到通过\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e策略可见的行；如果某一行未通过 \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e策略，就会报错。\u003c/p\u003e\u003cp\u003e在多数情况下，\u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e命令也需要从其删除所针对的关系中的列读取数据（例如在\u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e子句或 \u003ccode class=\"literal\"\u003eRETURNING\u003c/code\u003e子句中）。这种情况下，该关系上也需要\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e权限，并且除了 \u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e策略外，还会应用适当的 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e或\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e策略。这样，用户除了必须通过\u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e或 \u003ccode class=\"literal\"\u003eALL\u003c/code\u003e策略获准删除这些行之外，还必须通过 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e或\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e策略访问正在被删除的行。\u003c/p\u003e\u003cp\u003e\u003ccode class=\"literal\"\u003eDELETE\u003c/code\u003e策略不能具有\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e表达式，因为它只适用于正在从关系中删除行的情况，所以没有新行需要检查。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#SQL-CREATEPOLICY-SUMMARY\" title=\"表 300. 按命令类型应用的策略\"\u003e表 300\u003c/a\u003e总结了不同类型的策略如何应用到特定命令上。在该表中，\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e检查\u003c/span\u003e”\u003c/span\u003e表示要检查策略表达式，若其返回假或 null 则抛出错误；而\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e筛选\u003c/span\u003e”\u003c/span\u003e表示若策略表达式返回假或 null，则该行会被静默忽略。\u003c/p\u003e\u003cdiv class=\"table\"\u003e\u003cp class=\"title\"\u003e\u003cstrong\u003e表 300. 按命令类型应用的策略\u003c/strong\u003e\u003c/p\u003e\u003cdiv class=\"table-contents\"\u003e\u003ctable class=\"table\"\u003e\u003cthead\u003e\u003ctr\u003e\u003cth rowspan=\"2\"\u003e命令\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eSELECT/ALL策略\u003c/code\u003e\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eINSERT/ALL策略\u003c/code\u003e\u003c/th\u003e\u003cth colspan=\"2\"\u003e\u003ccode class=\"literal\"\u003eUPDATE/ALL策略\u003c/code\u003e\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eDELETE/ALL策略\u003c/code\u003e\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e 表达式\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e 表达式\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e 表达式\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eWITH CHECK\u003c/code\u003e 表达式\u003c/th\u003e\u003cth\u003e\u003ccode class=\"literal\"\u003eUSING\u003c/code\u003e 表达式\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eSELECT\u003c/code\u003e / \u003ccode class=\"command\"\u003eCOPY ... TO\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e筛选现有行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eSELECT FOR UPDATE/SHARE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e筛选现有行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e筛选现有行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e检查新行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e筛选现有行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e并检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e筛选现有行\u003c/td\u003e\u003ctd\u003e检查新行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eDELETE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e筛选现有行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e筛选现有行\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eINSERT ... ON CONFLICT\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.id-1.9.3.75.6.3.4.2.5.6.2.1\"\u003e\u003csup\u003e[b]\u003c/sup\u003e\u003c/a\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-PRIV\"\u003e\u003csup\u003e[c]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-PRIV\"\u003e\u003csup\u003e[c]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eON CONFLICT DO UPDATE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e检查现有行和新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-UPDATE-PRIV\"\u003e\u003csup\u003e[d]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e检查现有行\u003c/td\u003e\u003ctd\u003e检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-ON-CONFLICT-UPDATE-PRIV\"\u003e\u003csup\u003e[d]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eMERGE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e筛选源行和目标行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eMERGE ... THEN INSERT\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e检查新行 \u003ca href=\"/docs/18/sql-createpolicy.html#ftn.RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e\u003c/td\u003e\u003ctd\u003e检查新行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eMERGE ... THEN UPDATE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e检查新行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e检查现有行\u003c/td\u003e\u003ctd\u003e检查新行\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003ccode class=\"command\"\u003eMERGE ... THEN DELETE\u003c/code\u003e\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e—\u003c/td\u003e\u003ctd\u003e检查现有行\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd colspan=\"6\"\u003e\u003cdiv class=\"footnote\"\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#RLS-SELECT-PRIV\"\u003e\u003csup\u003e[a]\u003c/sup\u003e\u003c/a\u003e 如果需要读取现有行或新行，例如在 \u003ccode class=\"literal\"\u003eWHERE\u003c/code\u003e 或 \u003ccode class=\"literal\"\u003eRETURNING\u003c/code\u003e 子句引用该关系的列时。\u003c/p\u003e\u003c/div\u003e\u003cdiv class=\"footnote\"\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#id-1.9.3.75.6.3.4.2.5.6.2.1\"\u003e\u003csup\u003e[b]\u003c/sup\u003e\u003c/a\u003e 如果指定了仲裁索引或约束。\u003c/p\u003e\u003c/div\u003e\u003cdiv class=\"footnote\"\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#RLS-ON-CONFLICT-PRIV\"\u003e\u003csup\u003e[c]\u003c/sup\u003e\u003c/a\u003e 无论最终是否实际发生冲突，提议插入的行都会被检查。\u003c/p\u003e\u003c/div\u003e\u003cdiv class=\"footnote\"\u003e\u003cp\u003e\u003ca href=\"/docs/18/sql-createpolicy.html#RLS-ON-CONFLICT-UPDATE-PRIV\"\u003e\u003csup\u003e[d]\u003c/sup\u003e\u003c/a\u003e 指辅助\u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e命令中的新行，它可能与原始 \u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e命令中的新行不同。\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr\u003e\u003c/div\u003e\u003cdiv class=\"refsect2\"\u003e\u003ch3\u003e多条策略的应用\u003c/h3\u003e\u003cp\u003e当不同命令类型的多条策略应用于同一命令时（例如 \u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e和\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e策略应用于 \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e命令），用户必须同时具有这两种权限（例如既有从该关系中选取行的权限，也有更新这些行的权限）。因此，一种策略类型的表达式会与另一种策略类型的表达式使用 \u003ccode class=\"literal\"\u003eAND\u003c/code\u003e操作符组合。\u003c/p\u003e\u003cp\u003e当同一命令类型的多条策略应用于同一命令时，必须至少有一条 \u003ccode class=\"literal\"\u003ePERMISSIVE\u003c/code\u003e策略授予对该关系的访问权，并且所有 \u003ccode class=\"literal\"\u003eRESTRICTIVE\u003c/code\u003e策略都必须通过。因此，所有 \u003ccode class=\"literal\"\u003ePERMISSIVE\u003c/code\u003e策略表达式使用\u003ccode class=\"literal\"\u003eOR\u003c/code\u003e 组合，所有\u003ccode class=\"literal\"\u003eRESTRICTIVE\u003c/code\u003e策略表达式使用 \u003ccode class=\"literal\"\u003eAND\u003c/code\u003e组合，然后再将两者的结果使用 \u003ccode class=\"literal\"\u003eAND\u003c/code\u003e组合。如果没有 \u003ccode class=\"literal\"\u003ePERMISSIVE\u003c/code\u003e策略，则访问被拒绝。\u003c/p\u003e\u003cp\u003e请注意，就组合多条策略而言，\u003ccode class=\"literal\"\u003eALL\u003c/code\u003e策略会被视为与当前正在应用的其他策略同一类型。\u003c/p\u003e\u003cp\u003e例如，对于一个同时需要\u003ccode class=\"literal\"\u003eSELECT\u003c/code\u003e和 \u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e权限的\u003ccode class=\"literal\"\u003eUPDATE\u003c/code\u003e命令，如果这两类策略各自都有多个适用项，它们会按以下方式组合：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eRESTRICTIVE SELECT/ALL 策略 1 中的 \u003cem class=\"replaceable\"\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\nAND\nRESTRICTIVE SELECT/ALL 策略 2 中的 \u003cem class=\"replaceable\"\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\nAND\n...\nAND\n(\n  PERMISSIVE SELECT/ALL 策略 1 中的 \u003cem class=\"replaceable\"\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\n  OR\n  PERMISSIVE SELECT/ALL 策略 2 中的 \u003cem class=\"replaceable\"\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\n  OR\n  ...\n)\nAND\nRESTRICTIVE UPDATE/ALL 策略 1 中的 \u003cem class=\"replaceable\"\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\nAND\nRESTRICTIVE UPDATE/ALL 策略 2 中的 \u003cem class=\"replaceable\"\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\nAND\n...\nAND\n(\n  PERMISSIVE UPDATE/ALL 策略 1 中的 \u003cem class=\"replaceable\"\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\n  OR\n  PERMISSIVE UPDATE/ALL 策略 2 中的 \u003cem class=\"replaceable\"\u003e\u003ccode\u003e表达式\u003c/code\u003e\u003c/em\u003e\n  OR\n  ...\n)\n\u003c/pre\u003e\u003c/div\u003e","key":"parameters","title":"参数"},{"html":"\u003cp\u003e要为一个表创建或修改策略，你必须是该表的拥有者。\u003c/p\u003e\u003cp\u003e虽然策略会应用于针对数据库中表的显式查询，但当系统执行内部引用完整性检查或验证约束时，并不会应用这些策略。这意味着仍然存在间接判断某个给定值是否存在的方法。一个例子是，尝试向某个主键列或带有唯一约束的列插入重复值。如果插入失败，用户就能推断该值已经存在。（这个例子假定策略允许该用户插入自己无权看见的行。）另一个例子是，用户被允许向一个引用了另一张表的表中插入数据，而被引用的那张表本身对其是隐藏的。用户可以通过向引用表插入值来判断其存在性；插入成功就表示该值存在于被引用表中。要解决这些问题，可以仔细设计策略，防止用户插入、删除或更新那些可能暗示其本来无权看见的值是否存在的行，或者改用生成的值（例如代理键）来代替具有外部含义的键。\u003c/p\u003e\u003cp\u003e通常，为了防止受保护的数据无意间暴露给可能不可信的用户定义函数，系统会在应用用户查询中出现的条件之前，先强制执行安全策略施加的过滤条件。不过，被系统（或系统管理员）标记为 \u003ccode class=\"literal\"\u003eLEAKPROOF\u003c/code\u003e的函数和操作符由于被假定为可信，可以在策略表达式之前求值。\u003c/p\u003e\u003cp\u003e由于策略表达式会被直接添加到用户查询中，因此它们将以执行整个查询的用户权限运行。因此，使用某条策略的用户必须能够访问表达式中引用的所有表或函数，否则在尝试查询启用了行级安全的表时，只会收到权限被拒绝的错误。不过，这并不改变视图的工作方式。与普通查询和视图一样，被视图引用的表的权限检查和策略将使用视图所有者的权限，以及适用于视图所有者的任何策略；但如果视图是用 \u003ccode class=\"literal\"\u003esecurity_invoker\u003c/code\u003e选项定义的，则例外（见 \u003ca href=\"/docs/18/sql-createview.html\" title=\"CREATE VIEW\"\u003e\u003ccode class=\"command\"\u003eCREATE VIEW\u003c/code\u003e\u003c/a\u003e）。\u003c/p\u003e\u003cp\u003e对于\u003ccode class=\"command\"\u003eMERGE\u003c/code\u003e，不存在单独的策略。相反，执行 \u003ccode class=\"command\"\u003eMERGE\u003c/code\u003e时会根据实际执行的动作，应用为 \u003ccode class=\"command\"\u003eSELECT\u003c/code\u003e、\u003ccode class=\"command\"\u003eINSERT\u003c/code\u003e、\u003ccode class=\"command\"\u003eUPDATE\u003c/code\u003e和\u003ccode class=\"command\"\u003eDELETE\u003c/code\u003e定义的策略。\u003c/p\u003e\u003cp\u003e更多讨论和实际示例见\u003ca href=\"/docs/18/ddl-rowsecurity.html\" title=\"5.9. 行安全性策略\"\u003e第 5.9 节\u003c/a\u003e。\u003c/p\u003e","key":"notes","title":"注解"},{"html":"\u003cp\u003e\u003ccode class=\"command\"\u003eCREATE POLICY\u003c/code\u003e是一种\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e扩展。\u003c/p\u003e","key":"compatibility","title":"兼容性"},{"html":"\u003cspan class=\"simplelist\"\u003e\u003ca href=\"/wiki/sql/alter-policy/?v=18\" title=\"ALTER POLICY\"\u003e\u003cspan class=\"refentrytitle\"\u003eALTER POLICY\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/drop-policy/?v=18\" title=\"DROP POLICY\"\u003e\u003cspan class=\"refentrytitle\"\u003eDROP POLICY\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/alter-table/?v=18\" title=\"ALTER TABLE\"\u003e\u003cspan class=\"refentrytitle\"\u003eALTER TABLE\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e","key":"see_also","title":"另见"}],"sections_same_as":"","synopsis_html":"CREATE POLICY \u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e ON \u003cem class=\"replaceable\"\u003e\u003ccode\u003etable_name\u003c/code\u003e\u003c/em\u003e\n    [ AS { PERMISSIVE | RESTRICTIVE } ]\n    [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]\n    [ TO { \u003cem class=\"replaceable\"\u003e\u003ccode\u003erole_name\u003c/code\u003e\u003c/em\u003e | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]\n    [ USING ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003eusing_expression\u003c/code\u003e\u003c/em\u003e ) ]\n    [ WITH CHECK ( \u003cem class=\"replaceable\"\u003e\u003ccode\u003echeck_expression\u003c/code\u003e\u003c/em\u003e ) ]","synopsis_text":"CREATE POLICY name ON table_name\n[ AS { PERMISSIVE | RESTRICTIVE } ]\n[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]\n[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]\n[ USING ( using_expression ) ]\n[ WITH CHECK ( check_expression ) ]"}},"RequestedLocale":"zh-Hans","Fallback":false,"Versions":["10","11","12","13","14","15","16","17","18","19","20","9.5","9.6"],"Locales":["en","zh-Hans"],"Signatures":null,"Spellings":null,"SQLState":null,"Evidence":null}
