{"id":66573,"date":"2016-08-02T14:21:13","date_gmt":"2016-08-02T14:21:13","guid":{"rendered":"https:\/\/www.simple-talk.com\/?p=66573"},"modified":"2021-08-24T13:39:30","modified_gmt":"2021-08-24T13:39:30","slug":"sql-server-access-control-basics","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/database-administration-sql-server\/sql-server-access-control-basics\/","title":{"rendered":"SQL Server Access Control: The Basics"},"content":{"rendered":"<p>SQL Server provides a number of settings for controlling access to data, metadata, and other SQL Server resources. For those who are new to SQL Server security or don\u2019t manage security routinely, configuring these settings can seem a complex and confusing process. If you get the settings right, everybody is happy, but if you get them wrong, your users might not be able to access the data they need or, worse still, unauthorized users might be able to get at sensitive information or carry out malicious attacks.<\/p>\n<p>To effectively protect SQL Server, you must be able to provide approved users with the access they need to specific SQL Server resources, without compromising those or other resources, a process that involves the use of three important types of components:<\/p>\n<ul>\n<li><strong>Principals:<\/strong> Entities that can be authenticated to access the SQL Server resources. For example, your Windows login can be configured as a principal that allows you to connect to a SQL Server database. SQL Server supports three types of principals: logins, users, and roles. Logins exist at the server level, users exist at the database level, and roles can exist at either level.<\/li>\n<li><strong>Securables:<\/strong> SQL Server resources that can be accessed by a principal. Securables are the actual resources you\u2019re trying to protect, whether at the server level (e.g., availability groups), database level (e.g., full-text catalog), or the schema level (e.g., table or function).<\/li>\n<li><strong>Permissions:<\/strong> Types of access granted on a securable to a specific principal. For example, you can grant a Windows login (the principal) the ability to view data (the permission) in a specific database schema (the securable).<\/li>\n<\/ul>\n<p>Together, these three types of components can help you protect a SQL Server environment and its data at every level, from the availability groups down to the individual database objects. Generally, the process used for providing access to SQL Server resources is to create the principals you need and then configure them with the necessary permissions to access specific securables.<\/p>\n<h2>Server login principals<\/h2>\n<p>Logins provide a mechanism for users to connect to the SQL Server platform at the server level. A login serves as a user\u2019s initial entry point into the system. Generally, your first step in providing access for your users is to set up the necessary logins so they can make the initial connections to the server. The database engine supports two types of logins: Windows and SQL Server.<\/p>\n<p>A Windows login can be based on a Windows domain account\u2014either an individual user account or a group account\u2014or on a Windows local account. If based on a group account, any permissions granted to that login apply to all members of the group, which can be a handy approach to configuring security for multiple users who require the same level of access.<\/p>\n<p>To create a login, you can use SQL Server Management Studio (SSMS) or use the <strong>CREATE<\/strong> <strong>LOGIN<\/strong> T-SQL statement. For example, the following statement creates a login based for a local Windows user account (<strong>WinUser1<\/strong>) on the <strong>srv01b<\/strong> Windows computer:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">  CREATE LOGIN [srv01b\\WinUser1] FROM WINDOWS;\r\n<\/pre>\n<p>The <strong>FROM<\/strong> <strong>WINDOWS<\/strong> clause indicates that the login should be mapped to a Windows account. In this case, we\u2019ve specified the computer name and account name for a local user, but we could have instead specified a domain user, following the same format, as in <strong>WinDomain1\\WinUsr1<\/strong>. The <strong>CREATE<\/strong> <strong>LOGIN<\/strong> statement supports more options of course, depending on the type of user account being specified, but overall the statement is fairly straightforward. You\u2019re merely creating an object that exists at the server level to provide access to the SQL Server environment.<\/p>\n<p>If you\u2019re SQL Server installation is configured to run in mixed mode\u2014that is, it supports both Windows and SQL Server authentication methods\u2014you can also create SQL Server logins, which are specific to a SQL Server instance and not tied to Windows accounts in any way. Although Windows logins are generally the recommended approach, you might need to support SQL Server logins in specific situations, such as providing access to users who are not tied to a Windows domain. The built-in <strong>sa<\/strong> account, the bane of many in IT, is a type of SQL Server login.<\/p>\n<p>When users try to connect to SQL Server, the database engine validates their logins against the <strong>master<\/strong> database. This allows them to connect to the SQL Server instance, although they won\u2019t have the permissions necessary to do much else. In fact, to be able to access database resources, the login must be tied to a specific database user principal, which is then granted the permissions necessary to access the database objects.<\/p>\n<h2>Database user principals<\/h2>\n<p>A login\u2019s scope applies to the database engine as a whole, but it does not provide access to the individual database components. For the users associated with those logins to be able to access database resources, you must create users within the target databases and map those principals back to the server logins. You can create a database user with the same name as its associated login or with a different name. You can also map a login to users in multiple databases; however, a login can be mapped to only one user within a database at any given time.<\/p>\n<p>As with server-level logins, you can use SSMS or T-SQL to create a database user, but you must do so within the context of the specific database. For example, we can create a database user named <strong>DbUser1<\/strong> within the <strong>AdventureWorks2014<\/strong> database, based on the <strong>srv01b\\WinUser1<\/strong> login<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">USE AdventureWorks2014;\r\nGO\r\n\r\nCREATE USER DbUser1 FOR LOGIN [srv01b\\WinUser1];\r\n<\/pre>\n<p>The <strong>FOR<\/strong> <strong>LOGIN<\/strong> clause provides the necessary mapping back to the server login. We could have created the user with the same name as the login, but I used a different name here to demonstrate how easy it is to choose whatever name you like, as long as it is unique within the database. This approach also allows us to simplify the qualified name being used for the login.<\/p>\n<p>As you can see, creating a database user that maps back to a server login is a fairly straightforward process. The two principals work in conjunction with each other to enable a user to access the server and database, assuming the necessary permissions have also been configured for that user.<\/p>\n<p>Note that you can also create database users that do not map back to a server login. In other words, you can create users without creating logins. These types of users are generally used for contained databases that can be easily moved between SQL Server instances. For this reason, a database\u2019s containment feature must be enabled before you can create these types of users.<\/p>\n<h2>Server and database roles<\/h2>\n<p>After you create a login or user principal, you can configure permissions on either one to control access at the server or database level. Before you do that, however, consider that SQL Server also supports a third type of principal, referred to as a <em>role<\/em>. A role can exist at either the server or database level and can help manage user access to securables more efficiently.<\/p>\n<p>You can think of a role as a type of container for holding one or more logins, users, or other roles, similar to how a Windows group can hold multiple individual and group accounts. This can make managing multiple principals easier when those principals require the same type of access to SQL Server. You can configure each role with permissions to specific resources, adding or removing logins and users from these roles as needed.<\/p>\n<p>SQL Server supports three types of roles: server, database, and application. Server roles share the same scope as logins, which means they operate at the server level and pertain to the database engine as a whole. As a result, you can add only server-level principals to the roles, and you can configure the roles with permissions only to server-level securables, not database-level securables.<\/p>\n<p>SQL Server provides a set of fixed server roles that are each preconfigured with a set of permissions that cannot be changed. The fixed roles allow the principals assigned to those roles to carry out specific tasks. For example, members of the <strong>sysadmin<\/strong> fixed server role can perform any actions on the server, but members of the <strong>serveradmin<\/strong> role can only change server-wide configuration options and shut down the server.<\/p>\n<p>To view a list of fixed server roles, you can run the <strong>sp_helpsrvrole<\/strong> system stored procedure, as shown in the following example:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">  EXEC sp_helpsrvrole;\r\n<\/pre>\n<p>As of SQL Server 2012, you can also create user-defined server roles that let you configure the permissions however you need to. Creating a server role is as simple as creating any other type of principle. For instance, you can define a <strong>CREATE<\/strong> <strong>SERVER<\/strong> <strong>ROLE<\/strong> statement that specifies nothing more than the name of the role, as shown in the following example:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">  CREATE SERVER ROLE SrvRole1;\r\n<\/pre>\n<p>In this case, we\u2019re creating a server role name <strong>SrvRole1<\/strong>. However, the role exists only as a server-level object on the SQL Server instance, without the capacity to do anything. From here, we must add the login principals we want to include in the role and eventually configure the role with the necessary permissions. (We can actually add the principals and configure the permissions in whatever order we want.)<\/p>\n<p>To add a principal to the <strong>SrvRole1<\/strong> server role, we can use the <strong>ALTER<\/strong> <strong>SERVER<\/strong> <strong>ROLE<\/strong> statement, as shown in the following example:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">  ALTER SERVER ROLE SrvRole1 ADD MEMBER [srv01b\\WinUser1];\r\n<\/pre>\n<p>The statement includes the <strong>ADD<\/strong> <strong>MEMBER<\/strong> clause, which specifies the <strong>srv01b\\WinUser1<\/strong> server login. At this point, we could add other logins or user-defined roles, but we cannot add a fixed server role.<\/p>\n<p>At times, you will likely want to be able to track which principals have been assigned to your roles. You can use SSMS or you can create a T-SQL query that retrieves data from the <strong>sys.server_principals<\/strong> and <strong>sys.server_role_members<\/strong> catalog views, as shown in the following example:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">SELECT m.name MemberName\r\nFROM sys.server_role_members rm \r\n  JOIN sys.server_principals r\r\n    ON rm.role_principal_id = r.principal_id\r\n  JOIN sys.server_principals m\r\n    ON rm.member_principal_id = m.principal_id\r\nWHERE r.name = 'SrvRole1'; \r\n<\/pre>\n<p>The <strong>sys.server_role_members<\/strong> catalog view merely matches the principal IDs of the server roles to their members. To get the information we need, we must join each column in the view to the <strong>principal_id<\/strong> column in the <strong>sys.server_principals<\/strong> catalog view. The statement also includes a <strong>WHERE<\/strong> clause to limit the results to the <strong>SrvRole1<\/strong> server role. As expected, the statement returns only the value <strong>srv01b\\WinUser1<\/strong>.<\/p>\n<p>Creating a database role is just as simple as creating a server role. As before, we can use SSMS or issue a T-SQL statement, in this case, the <strong>CREATE<\/strong> <strong>ROLE<\/strong> statement. For instance, the following example creates the <strong>DbRole1<\/strong> database role:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">  CREATE ROLE DbRole1;\r\n<\/pre>\n<p>To add a principal to the <strong>DbRole1<\/strong> database role, we can use the <strong>ALTER<\/strong> <strong>ROLE<\/strong> statement, as shown in the following example:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">  ALTER ROLE DbRole1 ADD MEMBER DbUser1;\r\n<\/pre>\n<p>In this case, we\u2019ve added the <strong>DbUser1<\/strong> principal. Similar to server roles, we can add other database users or user-defined database roles, but not fixed database roles or any type of server principal.<\/p>\n<p>SQL Server also include catalog views for retrieving information about database roles and principals. For example, the following <strong>SELECT<\/strong> statement uses the <strong>sys.database_principals<\/strong> and <strong>sys.database_role_members<\/strong> catalog views to retrieve the members of the <strong>DbRole1<\/strong> database role:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">SELECT m.name MemberName\r\nFROM sys.database_role_members rm \r\n  JOIN sys.database_principals r\r\n    ON rm.role_principal_id = r.principal_id\r\n  JOIN sys.database_principals m\r\n    ON rm.member_principal_id = m.principal_id\r\nWHERE r.name = 'DbRole1'; \r\n<\/pre>\n<p>This statement is much like the one we used to retrieve details about the <strong>SrvRole1<\/strong> server role, only this case, its focus is on the <strong>DbRole1<\/strong> database role and consequently returns the value <strong>DbUser1<\/strong>.<\/p>\n<h2>Securables and permissions<\/h2>\n<p>Once we have our principals in place, we can start assigning them the permissions they need to access the various <em>securables.<\/em> A securable is a specific SQL Server resource whose access is controlled by the database engine through the use of permissions.<\/p>\n<p>SQL Server includes securables at three different scopes:<\/p>\n<ul>\n<li>Server-scoped securables include such resources as logins, server roles, availability groups, endpoints, and databases as a whole.<\/li>\n<li>Database-scoped securables include such resources as users, database roles, certificates, asymmetric keys, assemblies, full-text catalogs, and schemas as a whole.<\/li>\n<li>Schema-scoped securables include such resources as tables, views, types, functions, procedures, and XML schema collections.<\/li>\n<\/ul>\n<p>For each securable, SQL Server supports a set of permissions that are specific to that securable\u2019s scope and function. You can grant, deny, or revoke permissions on any securable to any principal, within the context of the specific principal and securable. For example, you can grant the <strong>SELECT<\/strong> permission on the <strong>Employee<\/strong> table to the <strong>DbUser1<\/strong> database user, which allows the user to retrieve data from that table.<\/p>\n<p>SQL Server supports three T-SQL statements for configuring permissions on a principal:<\/p>\n<ul>\n<li><strong>GRANT:<\/strong> Grants permissions on a securable to a principal.<\/li>\n<li><strong>DENY:<\/strong> Denies permissions on a securable to a principal. This can be important because it prevents the principal from inheriting other permissions that it has been granted.<\/li>\n<li><strong>REVOKE:<\/strong> Removes previously granted or denied permissions on a securable to a principal.<\/li>\n<\/ul>\n<p>Each of these statements supports a fairly complex syntax, coupled with the intricacies of the permission structure itself. A good place to start to more fully understand how permissions work is with the MSDN article <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms191291.aspx\">Permissions (Database Engine)<\/a>. You might also want to review the SQL Server documentation about each of the permission-related statements:<\/p>\n<ul>\n<li><a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms187965.aspx\">GRANT (Transact-SQL)<\/a><\/li>\n<li><a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms188338.aspx\">DENY (Transact-SQL)<\/a><\/li>\n<li><a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms187728.aspx\">REVOKE (Transact-SQL)<\/a><\/li>\n<\/ul>\n<p>Let\u2019s look at a few examples that demonstrate principals, securables, and permissions in action. We\u2019ll start by running an <strong>EXECUTE<\/strong> <strong>AS<\/strong> statement to change the execution context of our session to the <strong>DbUser1<\/strong> database user account in the <strong>AdventureWorks2014<\/strong> database:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">  EXECUTE AS USER = 'DbUser1';\r\n<\/pre>\n<p>Now let\u2019s try running the following T-SQL statements as <strong>DbUser1<\/strong>:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">SELECT * FROM HumanResources.Employee; \r\n\r\nSELECT * FROM HumanResources.EmployeePayHistory;\r\n\r\nSELECT * FROM HumanResources.JobCandidate; \r\n\r\nSELECT * FROM Person.Person; \r\n\r\nEXEC HumanResources.uspUpdateEmployeeHireInfo \r\n  5, 'Design Engineer II', '2008-01-06', '2016-07-14', 44.2938, 2, 1;\r\n<\/pre>\n<p>In each case, we will receive an error indicating that the user does not have the permissions necessary to access the requested resources. The reason is, of course, that the user has not been granted these permissions. Before we can do that, however, we must run a <strong>REVERT<\/strong> statement to return to the context of the user that does have the necessary permissions (the user you likely logged in as originally):<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">  REVERT;\r\n<\/pre>\n<p>Now that we\u2019re back to our old selves, let\u2019s use a <strong>GRANT<\/strong> statement to grant the <strong>EXECUTE<\/strong> permission on the <strong>uspUpdateEmployeeHireInfo<\/strong> stored procedure to the <strong>DbRole1<\/strong> database role, which includes the <strong>DbUser1<\/strong> database user:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">  GRANT EXECUTE ON OBJECT::HumanResources.uspUpdateEmployeeHireInfo TO DbRole1; \r\n<\/pre>\n<p>This example shows the <strong>GRANT<\/strong> statement in one of its simplest forms. However, as pointed out earlier, the statement supports a complex syntax that provides numerous options, depending on the securables and principals.<\/p>\n<p>After granting the necessary permissions, we can rerun the previous <strong>EXECUTE<\/strong> <strong>AS<\/strong> statement to change the context back to <strong>DbUser1<\/strong> and then rerun the <strong>SELECT<\/strong> and <strong>EXECUTE<\/strong> statements. This time, we\u2019ll still receive errors when we try to run the <strong>SELECT<\/strong> statements, but the <strong>EXECUTE<\/strong> statement will run fine.<\/p>\n<p>What\u2019s interesting about this is that the stored procedure updates the <strong>Employee<\/strong> table and inserts a role in the <strong>EmployeePayHistory<\/strong> table, even though <strong>DbUser1<\/strong> has not been granted this type of access to these tables. This works because the owner of the stored procedure, <strong>dbo<\/strong>, has access to the underlying tables, a process referred to as ownership chaining. You can find a great discussion about this topic in Phil Factor\u2019s Simple-Talk article <a href=\"https:\/\/www.simple-talk.com\/sql\/sql-training\/schema-based-access-control-for-sql-server-databases\/\">Schema-Based Access Control for SQL Server Databases<\/a>.<\/p>\n<p>Now let\u2019s revert back to our original user and run the following <strong>GRANT<\/strong> and <strong>DENY<\/strong> statements:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">GRANT SELECT ON SCHEMA::HumanResources TO DbRole1;\r\nDENY SELECT ON OBJECT::HumanResources.JobCandidate TO DbRole1;  \r\n<\/pre>\n<p>This time around, we\u2019re granting the <strong>SELECT<\/strong> permission on the <strong>HumanResources<\/strong> schema to the <strong>DbRole1<\/strong> database role, but denying the <strong>SELECT<\/strong> permission on the <strong>JobCandidate<\/strong> table, which is part of that schema. If we do not explicitly issue a <strong>DENY<\/strong> statement, the user would be able to access the table because it is part of the <strong>HumanResources<\/strong> schema.<\/p>\n<p>If we again change the session context back to <strong>DbUser1<\/strong> and then rerun the <strong>SELECT<\/strong> and <strong>EXECUTE<\/strong> statements, we will now be able to run the stored procedure and retrieve data from the <strong>Employee<\/strong> and <strong>EmployeePayHistory<\/strong> tables, but we will not be able to retrieve data from the <strong>JobCandidate<\/strong> or <strong>Person<\/strong> table because the <strong>DbUser1<\/strong> user has been explicitly denied <strong>SELECT<\/strong> permission on the <strong>JobCandidate<\/strong> table and the <strong>Person<\/strong> table is in the <strong>Person<\/strong> schema, not <strong>HumanResources<\/strong>, so no access has been granted.<\/p>\n<p>At some point, you\u2019ll likely want to be able to view the permissions you have configured on a specific securable (after reverting back to an authorized user). One way you can do this is to run a <strong>SELECT<\/strong> statement that joins the <strong>sys.database_principals<\/strong>, <strong>sys.database_permissions<\/strong>, and <strong>sys.schemas<\/strong> catalog views, as shown in the following example:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">SELECT pm.state_desc PermType,\r\n  pm.permission_name PermName, \r\n  pm.class_desc PermClass, \r\n  CASE\r\n    WHEN pm.class_desc = 'schema' THEN sc.name\r\n    ELSE OBJECT_NAME(pm.major_id)\r\n  END ObjectName\r\nFROM sys.database_principals pr\r\n  LEFT JOIN sys.database_permissions pm\r\n    ON pr.principal_id = pm.grantee_principal_id\r\n  LEFT JOIN sys.schemas sc\r\n    ON pm.major_id = sc.schema_id\r\nWHERE pr.name = 'DbRole1';\r\n<\/pre>\n<p>We have to include the <strong>sys.schema<\/strong> catalog view in the mix because the <strong>major_id<\/strong> value in the <strong>sys.database_permissions<\/strong> catalog view does not map to the actual schema name, as do other object types, so I chose to join the <strong>sys.schema<\/strong> catalog view in this way to give me what I need. The statement returns the following results, which show the permissions we granted to the <strong>DbRole1<\/strong> principal.<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<p><strong>PermType<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>PermName<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>PermClass<\/strong><\/p>\n<\/td>\n<td>\n<p><strong>ObjectName<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>GRANT<\/p>\n<\/td>\n<td>\n<p>EXECUTE<\/p>\n<\/td>\n<td>\n<p>OBJECT_OR_COLUMN<\/p>\n<\/td>\n<td>\n<p>uspUpdateEmployeeHireInfo<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>DENY<\/p>\n<\/td>\n<td>\n<p>SELECT<\/p>\n<\/td>\n<td>\n<p>OBJECT_OR_COLUMN<\/p>\n<\/td>\n<td>\n<p>JobCandidate<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>GRANT<\/p>\n<\/td>\n<td>\n<p>SELECT<\/p>\n<\/td>\n<td>\n<p>SCHEMA<\/p>\n<\/td>\n<td>\n<p>HumanResources<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>At any point in the process, we can revoke the permissions that have been granted on a securable to a principal. For example, the following <strong>REVOKE<\/strong> statements remove all the permissions we configured on the <strong>DbRole1<\/strong> database role:<\/p>\n<pre class=\"lang:tsql theme:ssms2012\">REVOKE EXECUTE ON OBJECT::HumanResources.uspUpdateEmployeeHireInfo TO DbRole1;\r\nREVOKE SELECT ON SCHEMA::HumanResources TO DbRole1;\r\nREVOKE SELECT ON OBJECT::HumanResources.JobCandidate TO DbRole1;  \r\n<\/pre>\n<p>Once you run these statements, the principals that have been added to the <strong>DbRole1<\/strong> role will no longer have access to the specified securables, unless they\u2019ve been granted access in another way.<\/p>\n<h2>Principals, securables, and permissions<\/h2>\n<p>There is much more to controlling SQL Server access than what we\u2019ve covered here, and you should view this information only as a starting point. The T-SQL statements can be far more intricate, and the securable\/permission mappings much more extensive.<\/p>\n<p>Orchestrating access to SQL Server resources takes time and careful consideration. The more complex the system, the more work involved. That\u2019s why using Windows groups along with server and database roles can be so helpful in mitigating some of the challenges of an involved implementation. They can help you grant access to SQL Server resources with just a few steps, making it relatively easy to make various server and database resources available to your users.<\/p>\n<p>Of course, the flip side to this is that it can be just as easy to open up resources to unauthorized users. How often have administrators, when faced with approaching deadlines and failed connections, opened up the database beyond what might have been necessary or advisable? Whenever you\u2019re setting up access in SQL Server, you should always be thinking in terms of the principle of least privilege, no matter what the circumstances. And you should always be vigilant against inadvertently granting access to those who shouldn\u2019t have it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>No technology yet invented can in any way allow us to neglect the task of ensuring the security of  the database by controlling access.  Security must be applied in depth, and the database is designed provide a system that will thwart even the most determined external attack.  If it seems a bit complicated at first, that is no longer an excuse now that Rob Sheldon has provided  this simple guide for getting started. &hellip;<\/p>\n","protected":false},"author":221841,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143527],"tags":[],"coauthors":[6779],"class_list":["post-66573","post","type-post","status-publish","format-standard","hentry","category-database-administration-sql-server"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/66573","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221841"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=66573"}],"version-history":[{"count":6,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/66573\/revisions"}],"predecessor-version":[{"id":67367,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/66573\/revisions\/67367"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=66573"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=66573"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=66573"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=66573"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}