create permission for user to see only one view - sql

I have a db and create login and user,
this user is not able to see anything.
grant select on GuestView to PublicLogin
after this user see this view
but user can select anything
MY QUESTION
Why I can lock user to do any select insert / update?
I have tried this
It didn't work.
SELECT 'REVOKE SELECT ON ' + quotename('dbo') + '.' + quotename('AccessCheckpoint') + ' TO PublicLogin' FROM INFORMATION_SCHEMA.TABLES
SELECT 'REVOKE UPDATE ON ' + quotename('dbo') + '.' + quotename('AccessCheckpoint') + ' TO PublicLogin' FROM INFORMATION_SCHEMA.TABLES
SELECT 'REVOKE INSERT ON ' + quotename('dbo') + '.' + quotename('AccessCheckpoint') + ' TO PublicLogin' FROM INFORMATION_SCHEMA.TABLES
SELECT 'REVOKE DELETE ON ' + quotename('dbo') + '.' + quotename('AccessCheckpoint') + ' TO PublicLogin' FROM INFORMATION_SCHEMA.TABLES
SELECT 'REVOKE EXECUTE ON ' + quotename('dbo') + '.' + quotename('AccessCheckpoint') + ' TO PublicLogin' FROM INFORMATION_SCHEMA.TABLES
but again select works normally
select *from AccessCheckpoint

DECLARE #TableUsedInView NVARCHAR(100)
DECLARE #TableUsedInView2 NVARCHAR(100)
SET #TableUsedInView='PulibcTable1'
SET #TableUsedInView2='PulibcTable2'
SELECT 'REVOKE SELECT ON ' + quotename(table_schema) + '.' + quotename(table_name) + ' TO PublicLogin'
FROM INFORMATION_SCHEMA.TABLES
WHERE table_name NOT IN(#TableUsedInView,#TableUsedInView2)
SELECT 'REVOKE UPDATE ON ' + quotename(table_schema) + '.' + quotename(table_name) + ' TO PublicLogin'
FROM INFORMATION_SCHEMA.TABLES
SELECT 'REVOKE DELETE ON ' + quotename(table_schema) + '.' + quotename(table_name) + ' TO PublicLogin'
FROM INFORMATION_SCHEMA.TABLES
SELECT 'REVOKE INSERT ON ' + quotename(table_schema) + '.' + quotename(table_name) + ' TO PublicLogin'
FROM INFORMATION_SCHEMA.TABLES
SELECT 'REVOKE EXECUTE ON ' + quotename(routine_schema) + '.' + quotename(routine_name) + ' TO PublicLogin'
FROM INFORMATION_SCHEMA.ROUTINES
SELECT 'GRANT SELECT ON GuestView to PublicLogin'
SELECT 'GRANT SELECT ON ' + #TableUsedInView + ' TO PublicLogin'
SELECT 'GRANT SELECT ON ' + #TableUsedInView2 + ' TO PublicLogin'
Copy those results and paste them into a new query window and run them. You should review the output to be sure you include only the views and procedures you need.
UPDATE:
This is to make sure that the user does not have any permissions from before on the tables. If you do as I wrote above you can create the following query in the Guest View:
SELECT *
FROM PulibcTable1 AS P
INNER JOIN PulibcTable2 AS P2 ON P.UserID=P2.UserID
But Public login will not be able to get rows if you have this in view:
SELECT *
FROM InternTable
This is because he has access only to read from the 2 tables

Related

How to get sum of multiple rows in a table dynamically

I am trying to get the total sum from columns of a specific data type(money) for multiple tables in a database. Currently I am able to get the list of columns from specific tables but I am unable to get the sums from those columns.
This is what I have now
use database 1
Select + Column_Name
From information_schema.columns
Where TABLE_NAME = 'claimant'
and data_type = 'money'
The result looks something like below
table_name
column_name
table_1
column_a
table_1
column_b
table_1
column_c
what I would like
table_name
column_name
total_sum
table_1
column_a
66.20
table_1
column_b
300.50
table_1
column_c
5389.42
update for #Squirrel Here is the code I have but it's still giving me issues with truncation.
{
declare #sql nvarchar(max);
select #sql = 'with cte as (' + char(13)
+ 'select' + char(13)
+ string_agg(char(9) + quotename(column_name) + ' = sum(' + quotename(COLUMN_NAME) + ')', ',' + char(13)) + char(13)
+ 'from ' + max(quotename(table_name)) + char(13)
+ ')' + char(13)
+ 'select a.table_name, a.column_name, a.total_sum ' + char(13)
+ 'from cte ' + char(13)
+ 'cross apply (' + char(13)
+ char(9) + 'values' + char(13)
+ string_agg(char(9) + '(''' + table_name + ''',''' + column_name + ''',' + quotename(COLUMN_NAME) + ')', ',' + char(13)) + char(13)
+ ') a (table_name, column_name, total_sum)'
from information_schema.columns AS A
INNER JOIN EDL01.STAGING.TABLE_DETAILS B
ON A.TABLE_NAME = B.DEST_TABLE_NAME
where A.table_name = B.DEST_TABLE_NAME
and data_type = 'money'
print #sql
exec sp_executesql #sql
}
below is the create table
CREATE TABLE [staging].[TABLE_DETAILS](
[SOURCE_TABLE_NAME] [varchar](100) NULL,
[DEST_TABLE_NAME] [varchar](100) NULL,
[TYPE] [varchar](10) NULL,
[PRIORITY] [int] NULL,
[SOURCE_TABLE_DATABASE] [varchar](50) NULL,
[SOURCE_TABLE_SCHEMA] [varchar](50) NULL,
[DEST_TABLE_DATABASE] [varchar](50) NULL,
[DEST_TABLE_SCHEMA] [varchar](50) NULL
) ON [PRIMARY]
GO
Below is part of the results
select a.table_name, a.column_name, a.total_sum
from cte
cross apply (
values
('PAYMENT','BILLEDAMOUNT',[BILLEDAMOUNT]),
('PAYMENT','AMOUNT',[AMOUNT]),
('SIMS_PAYMENT','CHECKAMOUNT',[CHECKAMOUNT]),
('BILLREVIEWHEADER','JURISDICTIONAMOUNT1',[JURISDICTIONAMOUNT1]),
('BILLREVIEWHEADER','JURISDICTIONAMOUNT2',[JURISDICTIONAMOUNT2]),
('BILLREVIE
You need to form the query dynamically and then execute it using sp_executesql or exec()
Note : char(9) is tab, char(13) is carriage return. These are added to format the query so that it is readable when you print it out for verification.
declare #sql nvarchar(max);
select #sql = 'with cte as (' + char(13)
+ 'select' + char(13)
+ string_agg(char(9) + quotename(column_name) + ' = sum(' + quotename(column_name) + ')', ',' + char(13)) + char(13)
+ 'from ' + max(quotename(table_name)) + char(13)
+ ')' + char(13)
+ 'select a.table_name, a.column_name, a.total_sum ' + char(13)
+ 'from cte ' + char(13)
+ 'cross apply (' + char(13)
+ char(9) + 'values' + char(13)
+ string_agg(char(9) + '(''' + table_name + ''', ''' + column_name + ''',' + quotename(column_name) + ')', ',' + char(13)) + char(13)
+ ') a (table_name, column_name, total_sum)'
from information_schema.columns
where table_name = 'table_1'
and data_type = 'money'
print #sql
exec sp_executesql #sql
For your sample table, the generated dynamic query is
with cte as (
select
[column_a] = sum([column_a]),
[column_b] = sum([column_b]),
[column_c] = sum([column_c])
from [table_1]
)
select a.table_name, a.column_name, a.total_sum
from cte
cross apply (
values
('table_1', 'column_a',[column_a]),
('table_1', 'column_b',[column_b]),
('table_1', 'column_c',[column_c])
) a (table_name, column_name, total_sum)
EDIT
using a loop to iterate each table. Basically it execute above query for each of the table and insert the result into a temp table
see db<>fiddle demo
for earlier SQL Server version without string_agg(), use for xml path
select #sql = 'with cte as (' + char(13)
+ 'select' + char(13)
+ stuff
(
(
select ',' + quotename(COLUMN_NAME) + ' = sum(' + quotename(COLUMN_NAME) + ')'
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = #table
and DATA_TYPE = 'money'
for xml path('')
),
1, 1, ''
) + char(13)
+ 'from ' + max(quotename(#table)) + char(13)
+ ')' + char(13)
+ 'select a.table_name, a.column_name, a.total_sum ' + char(13)
+ 'from cte ' + char(13)
+ 'cross apply (' + char(13)
+ char(9) + 'values' + char(13)
+ stuff
(
(
select ',' + '(''' + TABLE_NAME + ''', ''' + COLUMN_NAME + ''',' + quotename(COLUMN_NAME) + ')'
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = #table
and DATA_TYPE = 'money'
for xml path('')
),
1, 1, ''
)
+ ') a (table_name, column_name, total_sum)' + char(13)

Transfer specific data from one server to another

I have 2 different sql servers (2 different databases).
The 2 servers have the same tables.
Now I want to transfer from Server 1's Person table to Server 2's Person table only the records with ID between 1.000 and 50.000.
How could I do it in the easiest way ?
Tried with Generate Scripts, but there isn't an option to select just those IDs, the script transfers all the records.
Tried by using a SELECT statement on Server 1 and exporting the data as CSV, then importing the CSV file on Server 2, but apparently there are some problems because of the datetimeoffset fields...
I had the same problem where I had data in 2 domains that could not see each other over the network, I had to get some date, not all data and move that to the "other" server.
I wrote a script that took all data from a file group and created a dump of that data as well as the script to load the data.
A little later they also started to dump data out to archive for data that needed to be retained as the "csv" version can always be restored, regardless of the database used "7 years" from now...
Anyway, it's just a big "print" statement that uses BCP to move massive amounts of data between servers. You can tweak it to do what you like, just alter the query a bit, the top of the file contains the "control" variables.
/*******************************************************************
this script will generate thebcp out commands for all data from the
users current connected database. The this script will only work if
both databases have the same ddl version, meaning same tables, same
columns same data definitions.
*******************************************************************/
SET NOCOUNT ON
GO
DECLARE #Path nvarchar(2000) = 'f:\export\' -- storage location for bcp dump (needs to have lots of space!)
, #Batchsize nvarchar(40) = '1000000' -- COMMIT EVERY n RECORDS
, #Xmlformat bit = 0 -- 1 for yes to xml format, 0 for not xml
, #SourceServerinstance nvarchar(200) = 'localhost'-- SQL Server \ Instance name
, #Security nvarchar(800) = ' -T ' -- options are -T (trusted), -Uloginid -Ploginpassword
, #GenerateDump bit = 0 -- 0 for storing data to disk, not 1 for loading from disk
, #FileGroup sysname = 'Data'; -- Table filegroup that we are intrested in
--> set output to text and execute the query, then copy the generated commands, validate and execucte them
--------------------------------Do not edit below this line-----------------------------------------------------------------
DECLARE #filter TABLE(TABLE_NAME sysname)
INSERT INTO #filter (TABLE_NAME)
SELECT o.name
FROM sys.indexes as i
JOIN sys.objects as o on o.object_id = i.object_id
WHERE i.data_space_id = FILEGROUP_ID(#FileGroup)
AND i.type_desc ='CLUSTERED'
and o.name not like 'sys%'
order by 1
if(#GenerateDump=0)
begin
--BCP-OUT TABLES
SELECT 'bcp "' + QUOTENAME( TABLE_CATALOG ) + '.' + QUOTENAME( TABLE_SCHEMA )
+ '.' + QUOTENAME( TABLE_NAME ) + '" out "' + #path + '' + TABLE_NAME + '.dat" -q -b"'
+ #batchsize + '" -e"' + #path + 'Error_' + TABLE_NAME + '.err" -n -CRAW -o"' + #path + ''
+ TABLE_NAME + '.out" -S"' + #SourceServerinstance + '" ' + #security + ''
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM #filter)
if(#Xmlformat=0)
begin
print 'REM CREATE NON-XML FORMAT FILE '
SELECT 'bcp "' + QUOTENAME( TABLE_CATALOG ) + '.' + QUOTENAME( TABLE_SCHEMA ) + '.'+
QUOTENAME( TABLE_NAME ) + '" format nul -n -CRAW -f "' + #path + ''
+ TABLE_NAME + '.fmt" -S"' + #SourceServerinstance + '" ' + #security + ''
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM #filter)
end
else
begin
PRINT 'REM XML FORMAT FILE'
SELECT 'bcp "' +QUOTENAME( TABLE_CATALOG ) + '.' + QUOTENAME( TABLE_SCHEMA )
+ '.' + QUOTENAME( TABLE_NAME ) + '" format nul -x -n -CRAW -f "'
+ #path + '' + TABLE_NAME + '.xml" -S"' + #SourceServerinstance + '" ' + #security + ''
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM #filter)
end
end
else
begin
print '--Make sure you backup your database first'
--GENERATE CONSTRAINT NO CHECK
PRINT '--NO CHECK CONSTRAINTS'
SELECT 'ALTER TABLE ' + QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME( TABLE_NAME ) + ' NOCHECK CONSTRAINT ' + QUOTENAME( CONSTRAINT_NAME )
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME IN (SELECT TABLE_NAME FROM #filter)
PRINT '--DISABLE TRIGGERS'
SELECT 'ALTER TABLE ' + QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME( TABLE_NAME ) + ' DISABLE TRIGGER ALL'
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM #filter)
--TRUNCATE TABLE
SELECT 'TRUNCATE TABLE ' +QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME( TABLE_NAME ) + '
GO '
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM #filter)
--BULK INSERT
SELECT DISTINCT 'BULK INSERT ' + QUOTENAME(TABLE_CATALOG) + '.'
+ QUOTENAME( TABLE_SCHEMA ) + '.' + QUOTENAME( TABLE_NAME ) + '
FROM ''' + #path + '' + TABLE_NAME + '.Dat''
WITH (FORMATFILE = ''' + #path + '' + TABLE_NAME + '.FMT'',
BATCHSIZE = ' + #batchsize + ',
ERRORFILE = ''' + #path + 'BI_' + TABLE_NAME + '.ERR'',
TABLOCK);
GO '
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM #filter)
--GENERATE CONSTRAINT CHECK CONSTRAINT TO VERIFY DATA AFTER LOAD
PRINT '--CHECK CONSTRAINT'
SELECT 'ALTER TABLE ' + QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME( TABLE_NAME ) + ' CHECK CONSTRAINT '
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM #filter)
SELECT 'ALTER TABLE ' + QUOTENAME(TABLE_SCHEMA)+'.'+ QUOTENAME( TABLE_NAME ) + ' ENABLE TRIGGER ALL'
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME IN (SELECT TABLE_NAME FROM #filter)
end
At the end the easiest way was to use create a linked server between the 2 and execute my queries taking data from both the servers and excluding the IDs from the first server.
Thanks to everyone for the responses.

Turn dynamic SELECT query into UPDATE stored procedure SQL

I am rather new to this and I am having a hard time into converting the below SQL query into an UPDATE statement for a stored procedure.
SELECT 'select'+
stuff((
SELECT ',' + 'dbo.' + Function_Name + '(' + Parameters_List + ')' FROM
[SPECIFIC_DATABASE]..Specific_table c WHERE c.Table_Name = t.Table_Name FOR
XML PATH('')),1,1,'')
+' from [' + Database_Name +'].[dbo].['+Table_Name+'] '
+ 'Where Audit_ID>' + CAST(#Audit_ID as nvarchar(100))
As 'Specific Queries'
FROM (SELECT Distinct Database_Name, Table_Name FROM [SPECIFIC_DATABASE]..Specific_table) t
The UPDATE query should be something like
UPDATE Table_name
SET Column_name = Function_Name(Parameters_List)
WHERE Audit_id >= #Audit_ID
FROM [SPECIFIC_DATABASE]..Specific_table
Any suggestions and guidelines on this would be much appreciated!
I think this should give you what you want, but I don't see any any reference to a Column_Name, so I'm assuming you will hardcode that.
select 'UPDATE tbl' + stuff((
select ' set Column_Name = ' + 'dbo.' + Function_Name + '(' + Parameters_List + ')'
from [SPECIFIC_DATABASE]..Specific_table c
where c.Table_Name = t.Table_Name
for xml PATH('')
), 1, 1, '')
+ ' from [' + Database_Name + '].[dbo].[' + Table_Name + '] tbl'
+ 'Where Audit_ID>'
+ CAST(#Audit_ID as nvarchar(100)) as 'Specific Queries'
from (
select distinct Database_Name, Table_Name
from [SPECIFIC_DATABASE]..Specific_table
) t
If the answer's not right then it might be helpful if you post what is the current output of your first query and maybe some more details as to what are the contents of the table called "Specific_table".

How to display the output and also save it in global temp table in ms-sql

Usually when we use select statement it displays the output, but when insert into is used,stores the result into temp table.i want to do both.Display result and store in temp table as well in dynamic sql.
IF #DisplayInSelect IS NOT NULL
SET #DisplayInSelect = ','+#DisplayInSelect
SET #SQL = 'IF EXISTS (SELECT DISTINCT a.'+#column_name+' FROM ['+#TableName+'] a where '+#FullCondition+' )'+
'SELECT DISTINCT ''Error at column: '+#Column_name+''' as [Error Records if found any are shown below],'''+ISNULL(#CustomErrorMessage,'ERROR')+''''+ISNULL(#DisplayInSELECT,'')+', a.'+#column_name+',* FROM ['+#TableName+'] a where '+#FullCondition+'
INSERT INTO ##error_check(SELECT DISTINCT ''Error at column: '+#Column_name+''' as [Error Records if found any are shown below],'''+ISNULL(#CustomErrorMessage,'ERROR')+''''+ISNULL(#DisplayInSELECT,'')+', a.'+#column_name+', *FROM ['+#TableName+'] a where '+#FullCondition+');
PRINT('IQR1 sql is'+#SQL)
EXEC(#SQL)
END
You have to use insert into table along with Exec. Try like this,
IF #DisplayInSelect IS NOT NULL
SET #DisplayInSelect = ',' + #DisplayInSelect
SET #SQL = 'IF EXISTS (SELECT DISTINCT a.' + #column_name + ' FROM [' + #TableName + '] a where ' + #FullCondition + ' )' + 'SELECT DISTINCT ''Error at column: ' + #Column_name + ''' as [Error Records if found any are shown below],''' + ISNULL(#CustomErrorMessage, 'ERROR') + '''' + ISNULL(#DisplayInSELECT, '') + ', a.' + #column_name + ',* FROM [' + #TableName + '] a where ' + #FullCondition + '
SELECT DISTINCT ''Error at column: ' + #Column_name + ''' as [Error Records if found any are shown below],''' + ISNULL(#CustomErrorMessage, 'ERROR') + '''' + ISNULL(#DisplayInSELECT, '') + ', a.' + #column_name + ', *FROM [' + #TableName + '] a where ' + #FullCondition + ';'
--To Save
INSERT INTO ##error_check
EXEC (#SQL)
PRINT (' IQR1 sql IS ' + #SQL)
--To Display
EXEC (#SQL)

Create select statement based on INFORMATION_SCHEMA.TABLES

I'm trying to create some overviews and eventually some dynamic select statements for a database.
select 'select ''' + TABLE_SCHEMA + '.' + TABLE_NAME + ''', count(*) from [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] union all'
from INFORMATION_SCHEMA.TABLES
where TABLE_TYPE != 'VIEW'
and (select count(*) from TABLE_SCHEMA.TABLE_NAME) > 0
I'm stuck on this part: select count(*) from TABLE_SCHEMA.TABLE_NAME
Which throws Invalid object name
Is there any way I can make that work dynamically?
If you want to exclude tables with no rows from your result set, add a HAVING COUNT(*) > 0 clause to your generated SQL:
select 'select ''' + TABLE_SCHEMA + '.' + TABLE_NAME + ''', count(*) from [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] having count(*) > 0 union all'
from INFORMATION_SCHEMA.TABLES
where TABLE_TYPE != 'VIEW'