I'm trying to write a query to tell me what tables in a database a certain user can access. This is a domain user and not just a SQL user.
Thanks in advance.
Assuming your only interested in users/logins as opposed to roles etc, you grab the information your after as follows:
WITH RootPermissions
AS ( SELECT USER_NAME(p.grantee_principal_id) AS UserName ,
dp.principal_id ,
dp.type_desc AS UserType ,
OBJECT_NAME(p.major_id) AS ObjectName ,
p.class_desc AS ObjectType ,
p.permission_name AS Permission,
p.state_desc AS PermissionState
FROM sys.database_permissions AS p
INNER JOIN sys.database_principals AS dp ON p.grantee_principal_id = dp.principal_id
),
UnionResults ( UserName, UserType, ObjectName, ObjectType, Permission, PermissionState, role_name )
AS ( SELECT UserName ,
UserType ,
ObjectName ,
ObjectType ,
Permission ,
PermissionState ,
CAST(NULL AS SYSNAME) AS role_name
FROM RootPermissions AS p
WHERE ( UserType <> 'DATABASE_ROLE' )
UNION
SELECT rm.member_principal_name ,
rm.principal_type_desc ,
p.ObjectType ,
p.ObjectName ,
p.Permission ,
p.PermissionState ,
rm.role_name
FROM RootPermissions AS p
RIGHT OUTER JOIN ( SELECT rm.role_principal_id ,
dp.type_desc AS principal_type_desc ,
rm.member_principal_id ,
USER_NAME(rm.member_principal_id) AS member_principal_name ,
USER_NAME(rm.role_principal_id) AS role_name
FROM sys.database_role_members AS rm
INNER JOIN sys.database_principals AS dp ON rm.member_principal_id = dp.principal_id
) AS rm ON rm.role_principal_id = p.principal_id
)
SELECT ObjectName ,
UserName ,
ObjectType ,
UserType ,
Permission ,
PermissionState ,
role_name
FROM UnionResults
WHERE ( ObjectName IS NOT NULL )
ORDER BY ObjectName ,
UserName
Related
I am attempting to remove permissions from a group to a schema in Redshift. I do not want to delete the group...just remove permissions to this one schema. I am executing this command:
revoke all
on schema heap2
from group ba_prod;
The query executes and does not fail.
To doublecheck that said permissions have been removed, I am running this SQL:
select distinct schemname ,
--objectname ,
username ,
usertype
from
(
select namespace schemname,
item objectname,
groname username,
'GROUP' usertype,
SPLIT_PART( SPLIT_PART( ARRAY_TO_STRING( RELACL, '|' ), pu.groname, 2 ) , '/', 1 ) char_perms
from
(
SELECT use.usename AS subject
,nsp.nspname AS namespace
,cls.relname AS item
,cls.relkind AS type
,use2.usename AS owner
,cls.relacl
FROM pg_user use
CROSS JOIN pg_class cls
LEFT JOIN pg_namespace nsp
ON cls.relnamespace = nsp.oid
LEFT JOIN pg_user use2
ON cls.relowner = use2.usesysid
WHERE cls.relowner = use.usesysid
--AND nsp.nspname NOT IN ('pg_catalog', 'pg_toast', 'information_schema')
and nsp.nspname = 'heap2'
ORDER BY subject
,namespace
,item )
JOIN pg_group pu ON array_to_string(relacl, '|') LIKE '%'|| pu.groname ||'%'
) as ucnu2p
Which shows that the group still has permission to the heap2 schema. What am I missing?
To doublecheck that said permissions have been removed, I am running this SQL:
select distinct schemname ,
--objectname ,
username ,
usertype
from
(
select namespace schemname,
item objectname,
groname username,
'GROUP' usertype,
SPLIT_PART( SPLIT_PART( ARRAY_TO_STRING( RELACL, '|' ), pu.groname, 2 ) , '/', 1 ) char_perms
from
(
SELECT use.usename AS subject
,nsp.nspname AS namespace
,cls.relname AS item
,cls.relkind AS type
,use2.usename AS owner
,cls.relacl
FROM pg_user use
CROSS JOIN pg_class cls
LEFT JOIN pg_namespace nsp
ON cls.relnamespace = nsp.oid
LEFT JOIN pg_user use2
ON cls.relowner = use2.usesysid
WHERE cls.relowner = use.usesysid
--AND nsp.nspname NOT IN ('pg_catalog', 'pg_toast', 'information_schema')
and nsp.nspname = 'heap2'
ORDER BY subject
,namespace
,item )
JOIN pg_group pu ON array_to_string(relacl, '|') LIKE '%'|| pu.groname ||'%'
) as ucnu2p
Which shows that the group still has permission to the heap2 schema. What am I missing?
I want to be able to query and filter tables based on it's size
I already know sp_spaceused, but it shows the size for one table at a time
Here's that view adjusted to use sys.pdw_permanent_table_mappings as per the Synapse recommendation
SELECT two_part_name, SUM( row_count ) AS row_count, SUM( reserved_space_GB ) AS reserved_space_GB
FROM dbo.vTableSizes
GROUP BY two_part_name
ORDER BY reserved_space_GB DESC;
The view:
ALTER VIEW dbo.vTableSizes
AS
WITH base
AS
(
SELECT
GETDATE() AS [execution_time]
, DB_NAME() AS [database_name]
, s.name AS [schema_name]
, t.name AS [table_name]
, QUOTENAME(s.name)+'.'+QUOTENAME(t.name) AS [two_part_name]
, nt.[name] AS [node_table_name]
, ROW_NUMBER() OVER(PARTITION BY nt.[name] ORDER BY (SELECT NULL)) AS [node_table_name_seq]
, tp.[distribution_policy_desc] AS [distribution_policy_name]
, c.[name] AS [distribution_column]
, nt.[distribution_id] AS [distribution_id]
, i.[type] AS [index_type]
, i.[type_desc] AS [index_type_desc]
, nt.[pdw_node_id] AS [pdw_node_id]
, pn.[type] AS [pdw_node_type]
, pn.[name] AS [pdw_node_name]
, di.name AS [dist_name]
, di.position AS [dist_position]
, nps.[partition_number] AS [partition_nmbr]
, nps.[reserved_page_count] AS [reserved_space_page_count]
, nps.[reserved_page_count] - nps.[used_page_count] AS [unused_space_page_count]
, nps.[in_row_data_page_count]
+ nps.[row_overflow_used_page_count]
+ nps.[lob_used_page_count] AS [data_space_page_count]
, nps.[reserved_page_count]
- (nps.[reserved_page_count] - nps.[used_page_count])
- ([in_row_data_page_count]
+ [row_overflow_used_page_count]+[lob_used_page_count]) AS [index_space_page_count]
, nps.[row_count] AS [row_count]
from
sys.schemas s
INNER JOIN sys.tables t
ON s.[schema_id] = t.[schema_id]
INNER JOIN sys.indexes i
ON t.[object_id] = i.[object_id]
AND i.[index_id] <= 1
INNER JOIN sys.pdw_table_distribution_properties tp
ON t.[object_id] = tp.[object_id]
INNER JOIN sys.pdw_permanent_table_mappings tm
ON t.[object_id] = tm.[object_id]
INNER JOIN sys.pdw_nodes_tables nt
ON tm.[physical_name] = nt.[name]
INNER JOIN sys.dm_pdw_nodes pn
ON nt.[pdw_node_id] = pn.[pdw_node_id]
INNER JOIN sys.pdw_distributions di
ON nt.[distribution_id] = di.[distribution_id]
INNER JOIN sys.dm_pdw_nodes_db_partition_stats nps
ON nt.[object_id] = nps.[object_id]
AND nt.[pdw_node_id] = nps.[pdw_node_id]
AND nt.[distribution_id] = nps.[distribution_id]
LEFT OUTER JOIN (select * from sys.pdw_column_distribution_properties where distribution_ordinal = 1) cdp
ON t.[object_id] = cdp.[object_id]
LEFT OUTER JOIN sys.columns c
ON cdp.[object_id] = c.[object_id]
AND cdp.[column_id] = c.[column_id]
WHERE pn.[type] = 'COMPUTE'
)
, size
AS
(
SELECT
[execution_time]
, [database_name]
, [schema_name]
, [table_name]
, [two_part_name]
, [node_table_name]
, [node_table_name_seq]
, [distribution_policy_name]
, [distribution_column]
, [distribution_id]
, [index_type]
, [index_type_desc]
, [pdw_node_id]
, [pdw_node_type]
, [pdw_node_name]
, [dist_name]
, [dist_position]
, [partition_nmbr]
, [reserved_space_page_count]
, [unused_space_page_count]
, [data_space_page_count]
, [index_space_page_count]
, [row_count]
, ([reserved_space_page_count] * 8.0) AS [reserved_space_KB]
, ([reserved_space_page_count] * 8.0)/1000 AS [reserved_space_MB]
, ([reserved_space_page_count] * 8.0)/1000000 AS [reserved_space_GB]
, ([reserved_space_page_count] * 8.0)/1000000000 AS [reserved_space_TB]
, ([unused_space_page_count] * 8.0) AS [unused_space_KB]
, ([unused_space_page_count] * 8.0)/1000 AS [unused_space_MB]
, ([unused_space_page_count] * 8.0)/1000000 AS [unused_space_GB]
, ([unused_space_page_count] * 8.0)/1000000000 AS [unused_space_TB]
, ([data_space_page_count] * 8.0) AS [data_space_KB]
, ([data_space_page_count] * 8.0)/1000 AS [data_space_MB]
, ([data_space_page_count] * 8.0)/1000000 AS [data_space_GB]
, ([data_space_page_count] * 8.0)/1000000000 AS [data_space_TB]
, ([index_space_page_count] * 8.0) AS [index_space_KB]
, ([index_space_page_count] * 8.0)/1000 AS [index_space_MB]
, ([index_space_page_count] * 8.0)/1000000 AS [index_space_GB]
, ([index_space_page_count] * 8.0)/1000000000 AS [index_space_TB]
FROM base
)
SELECT *
FROM size
;
The documented DMV queries allow you to get a report of all table sizes.
Expectation:
I would like to get all customers who bought an article from an specific category (i. e. drones) since the beginning of the year.
Problem:
I get duplicates; i. e. the customer purchased again at a different time (I don't care about that)
Relationship of the tables:
[Master_CustomerData] has_many
[Master_OrderHeader] has_many
[Master_OrderedArticles] belongs_to
[Master_ArticleBase]
SELECT
DISTINCT CD.SubscriberKey AS MCD_SubscriberKey
, MAX(OH.OrderDate) AS OH_OrderDate
, MAX(OA.OrderNo) AS OA_OrderNo
, OA.ArticleNo AS OA_ArticleNo
, OA.QuantityOrdered AS OA_QuantityOrdered
, AB.Category AS AB_Category
, CD.EmailAddress AS EmailAddress
, CD.EmailLanguage AS EmailLanguage
, CD.Gender AS Gender
, CD.FirstName AS FirstName
, CD.LastName AS LastName
FROM [Master_CustomerData] AS CD
INNER JOIN [Master_OrderHeader] AS OH
ON CD.SubscriberKey = OH.SubscriberKey
INNER JOIN [Master_OrderedArticles] AS OA
ON OH.OrderNo = OA.OrderNo
INNER JOIN [Master_ArticleBase] AS AB
ON OA.ArticleNo = AB.ArticleNo
WHERE
/* Category group */
AB.Category IN (811000)
AND OA.QuantityCancelled = 0
AND OH.OrderDate > '2018-01-01'
GROUP BY
CD.SubscriberKey
, CD.EmailAddress
, OA.ArticleNo
, OA.QuantityOrdered
, AB.Category
, CD.EmailLanguage
, CD.Gender
, CD.FirstName
, CD.LastName
for date you have max date so should not select duplicated value
if you use group by you don't need DISTINCT
could be you need sum for quantityOrdered too (if someone order two time the same product you have duplicated rows)
SELECT CD.SubscriberKey AS MCD_SubscriberKey
, MAX(OH.OrderDate) AS OH_OrderDate
, MAX(OA.OrderNo) AS OA_OrderNo
, OA.ArticleNo AS OA_ArticleNo
, SUM(OA.QuantityOrdered) AS OA_QuantityOrdered
, AB.Category AS AB_Category
, CD.EmailAddress AS EmailAddress
, CD.EmailLanguage AS EmailLanguage
, CD.Gender AS Gender
, CD.FirstName AS FirstName
, CD.LastName AS LastName
FROM [Master_CustomerData] AS CD
INNER JOIN [Master_OrderHeader] AS OH ON CD.SubscriberKey = OH.SubscriberKey
INNER JOIN [Master_OrderedArticles] AS OA ON OH.OrderNo = OA.OrderNo
INNER JOIN [Master_ArticleBase] AS AB ON OA.ArticleNo = AB.ArticleNo
WHERE AB.Category = 811000
AND OA.QuantityCancelled = 0
AND OH.OrderDate > '2018-01-01'
GROUP BY
CD.SubscriberKey
, CD.EmailAddress
, OA.ArticleNo
, AB.Category
, CD.EmailLanguage
, CD.Gender
, CD.FirstName
, CD.LastName
Here is my working solution. I removed the "distinct", maxed "AB.Category" and grouped by what has to be distinct.
Thx, for all answers...
SELECT
CD.SubscriberKey AS MCD_SubscriberKey
, MAX(OH.OrderDate) AS OH_OrderDate
, MAX(OA.OrderNo) AS OA_OrderNo
, MAX(AB.Category) AS AB_Category
, CD.EmailAddress AS EmailAddress
, CD.EmailLanguage AS EmailLanguage
, CD.Gender AS Gender
, CD.FirstName AS FirstName
, CD.LastName AS LastName
FROM [Master_CustomerData] AS CD
INNER JOIN [Master_OrderHeader] AS OH
ON CD.SubscriberKey = OH.SubscriberKey
INNER JOIN [Master_OrderedArticles] AS OA
ON OH.OrderNo = OA.OrderNo
INNER JOIN [Master_ArticleBase] AS AB
ON OA.ArticleNo = AB.ArticleNo
WHERE
/* Category defined: Dornes, cameras, outdoor, consoles */
AB.Category IN (
211000,
212000,
...
791700
)
/* Article not Cancelled */
AND OA.QuantityCancelled = 0
/* OrderDate */
AND OH.OrderDate > '2017-08-01'
GROUP BY
CD.SubscriberKey
, CD.EmailAddress
, CD.EmailLanguage
, CD.Gender
, CD.FirstName
, CD.LastName
I need to make a list of all tables in two or more databases on one server. This list needs to contain the TableName, Permission\Securable, Role\List role name and a Y/N for the permission.
I have tried several different options, however the results are significantly different than the report from last year (query from last year doesn't exist).
I am probably missing something obvious. What is happening is the table doesn't show in the results because there are no explicit permissions. However the report last year displays that there are. So I think I am just using the wrong method all together.
Here is the "Generic" for on the code I have attempted to utilize in my last attempt:
SELECT s.name AS [Schema]
, o.name AS Object
-- , u.name AS [User]
, dp.permission_name, dp.state_desc
FROM sys.database_permissions dp
JOIN sys.objects o ON dp.major_id = o.object_id
JOIN sys.schemas s ON o.schema_id = s.schema_id
JOIN sys.database_principals u ON dp.grantee_principal_id = u.principal_id
WHERE o.name = 'tables'--#ObjName
UNION ALL
SELECT s.name AS [Schema]
--, NULL
, u.name AS [User]
, dp.permission_name
, dp.state_desc
FROM sys.database_permissions dp
JOIN sys.schemas s ON dp.major_id = s.schema_id
JOIN sys.database_principals u ON dp.grantee_principal_id = u.principal_id
--ORDER BY s.name, o.name --, u.name
What I was Missing was Implied permissions Versus Explicit Permissions. I assumed explicted permissions were used, not implied\inheritied permissions.
I made this query to view the permissions of a role on the tables and the views.
DECLARE #RoleName VARCHAR(MAX) = 'role_gestionale'
IF OBJECT_ID('tempdb..#roles') IS NOT NULL DROP TABLE #roles
SELECT dp.major_id Object_id, dp.permission_name Permission
INTO #roles
FROM sys.database_permissions dp
INNER JOIN sys.database_principals u ON dp.grantee_principal_id = u.principal_id
WHERE u.name=#RoleName
SELECT *
FROM (
SELECT o.type_desc Tipo, s.name AS [SCHEMA], o.name AS [Table]
, (SELECT COUNT(*) FROM #roles r WHERE r.Object_id=o.object_id AND Permission='SELECT') AS [SELECT]
, (SELECT COUNT(*) FROM #roles r WHERE r.Object_id=o.object_id AND Permission='INSERT') AS [INSERT]
, (SELECT COUNT(*) FROM #roles r WHERE r.Object_id=o.object_id AND Permission='UPDATE') AS [UPDATE]
, (SELECT COUNT(*) FROM #roles r WHERE r.Object_id=o.object_id AND Permission='DELETE') AS [DELETE]
FROM sys.objects o
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE o.type_desc IN ('USER_TABLE', 'VIEW')
) a
--WHERE [INSERT]=0 OR [SELECT]=0 OR [UPDATE]=0 OR [DELETE]=0
ORDER BY 1, 2, 3
Alessandro Lettieri
I have a table named RoleDetails with this structure:
ROLE_ID - PK ,
NAME ,
PARENT_ROLE_ID FK ,
CREATED_BY_ID ,
MODIFIED_BY_ID
The other table is user_details
USER_ID ,
USERNAME ,
FULLNAME
How do I query this table so that in the result set
I get the RoleName, RoleId, ParentRoleId, ParentRoleName, CreatedByName and ModifiedByName.
So far I have tried:
SELECT
[ROLE_ID] AS ID, r.NAME AS [RoleName],
r.PARENT_ROLE_ID AS [ParentRoleID] ,
(SELECT rd.NAME FROM dbo.ROLES rd
WHERE rd.ROLE_ID = r.PARENT_ROLE_ID ) AS [ParentRoleName],
CONCAT(ud.FIRST_NAME, ' ', ud.LAST_name) AS [CreatedByName] ,
CONCAT(u.FIRST_NAME, ' ', u.LAST_name) AS [LastModifiedByName]
FROM
dbo.ROLES r
LEFT OUTER JOIN
user_details u ON r.MODIFIED_BY = u.USER_ID
LEFT OUTER JOIN
dbo.USER_DETAILS ud ON r.CREATED_BY = ud.USER_ID
WHERE
r.ROLE_ID = #iRoleID;
You will need to join the user_detail table twice. Once to get the create user and once to get the modify user.
SELECT rd.Name,
rd.Role_ID,
rd.Parent_role_id,
pr.Name,
ud.userName as CreatedByName,
udm.userName as ModifyByName
FROM RoleDetails as rd
INNER JOIN RoleDetails as pr
ON rd.Parent_Role_Id = pr.Role_id
INNER JOIN User_Detail as ud
on rd.Created_by_id = ud.user_id
INNER JOIN User_Detail as udm
ON rd.Modified_by_user = udm.user_id