Need to query SSRS database for report access - sql

I would like to know if there is a way to return in a SQL (2005) query (for all reports):
Report ID, Report Name, Report Path, User and Group Security, Datasources.
I know that I can go to my report server page and go to Properties > Security, but we have over 120 reports and I want to see if there is an easier way to get the information I need.
Thanks in advance!

A. Never ever query RS Database directly until you know what are you doing. The queries could acquires lock which could affect overall performance of RS.
B. To know about report execution stats, you can use ExecutionLog view in RS 2008 onwards or following query with NOLOCK Hint.
Select CAST(C.Name AS VARCHAR(20)) [Name],
E.ReportID,
E.InstanceName,
E.UserName,
E.RequestType,
E.Format,
E.Parameters,
E.TimeStart,
E.TimeEnd,
E.TimeDataRetrieval,
E.TimeProcessing,
E.TimeRendering,
E.Source,
E.Status,
E.ByteCount,
E.[RowCount]
from executionlog E WITH (NOLOCK) inner join catalog C WITH (NOLOCK)
on E.ReportID = C.ItemID
C. RS exposes almost all the functionality via SOAP APIs. For example this sample published my MS shows how to get security information on Report Items http://msftrsprodsamples.codeplex.com/wikipage?title=SS2008R2%21RSPermissions%20Sample%20Application&referringTitle=Home
To know more about RS SOAP APIs please see http://msdn.microsoft.com/en-us/library/ms154052.aspx

You can query the ReportServer database directly using something like SSMS. Most of what you're looking for can be found directly in the dbo.Catalog table:
SELECT *
FROM dbo.Catalog
WHERE Type = 2; -- 2 = Reports, 5 = Data Sources

Related

MS Access SQL error with Update Query

working on linking data between a SQL Server Database and MS Access. Right now someone is manually calculating Data from a SQL Database report and entering this into Access to run other reports within Access.
I have created a pass through query to pull the relevant information into an Access Table from the SQL Database( all working nicely )
Now I need to update the existing Access Tables with Data retrieved from the SQL pass through. I have tried a number of different queries all fussing at me for various reasons. Here is an example of the latest query that will get me what I need. This works if I setup a Sandbox in SQL Server and run it MSSQL Management Studio, but will not work in access
UPDATE JT
SET JT.ContractAmt = SBD.TotalSum
FROM JobTable_TEST AS JT
INNER JOIN (
SELECT Sum( Main.amt ) as TotalSum, Main.job
FROM Main
GROUP BY Main.job
) AS SBD
ON SBD.job = JT.JobNumber
In Access the Above Generates the following error "Syntax error( missing operator) in query expression.
Updating following attempt at using SQL Passthrough to run the update Query.
I updated my Query to do this directly from a Passthrough SQL Statement as suggested and get the following error.
ODBC--call failed.
[Microsoft][SQL Server Native Client 11.0][SQL Server]Invalid object name 'TableName'.(#208)
Here is what the pass through query i used looked like.
UPDATE AccessTable
SET AccessTable.amt = SQLResult.Total
FROM TableName AS AccessTable
INNER JOIN ( SELECT SUM( SQLTableA.amt) as Total, SQLTableA.job
FROM SQLTableA
LEFT OUTER JOIN SQLTableB ON (SQLTableA.company = SQLTableB.company)
AND (SQLTableA.job = SQLTableB.job)
GROUP BY SQLTableA.job
) AS SQLResult
ON SQLResult.job = AccessTable.JobNum
hopefully that better describes where my tables are located and how my update needs to happen, and maybe someone can point out how this is wrong or if it will even work this way.
Any suggestions would be greatly appreciated
It appears your subquery, aliased as SBD, is missing a job_no column. Therefore you aren't going to be able to join on it.

Using a query that is stored in a table

My database has two tables: t_computers and t_queries.
This query shows me which computers are laptops
select *
from t_computers
where type = 'Laptop'
In the table t_queries I have stored dynamic SQL queries.
SELECT QuerySQL
from t_query
where QueryName = 'Clients that have not been started in 30 days'
The first result is the SQL query that would give me this information.
Now for the complicated part, I want to only select computers that have the type 'Laptop' and are returned if I run the query that is stored in the table.
So something like this
select *
from t_computers
where type = 'Laptop' and
(computer is returned for (SELECT QuerySQL
from query
where QueryName = 'Clients that have not been started in 30 days'))
Is this even possible? I am using SQL Server 2008 R2
I have used a very simplified example.
Some background information on why I want to use the query saved in the table: With our Client Management System (similar to SCCM) Administrators can easily create "views" of Clients. For example Filtering out all Computers that have an IP starting with 10.*. As soon as they save the view, a SQL query is created and saved in the table t_queries. This one query that I want to compare against changes quite often.
Yes it is possible, but as said by the commenters, I strongly unadvise you to execute arbitrary code coming from your users, no matter how much you trust them. You would have very little possibilities to enforce security rules and may open yourself to devastating security breaches.
The way it is properly done in other systems is to use a specific query language (custom or not) that you interpret and "translate" to SQL if needed. That allows you to limit the possible operations to what is strictly necessary.
After that disclaimer, here is an answer to your question (untested, I don't have SQL Server on this laptop so I may have messed up a bit with the quotes) :
exec('select *
from t_computers
where type = ''Laptop'' and
(computer is returned for ('+SELECT TOP(1) QuerySQL
from query
where QueryName = 'Clients that have not been started in 30 days'+'))');

Ignore denied columns in "select * from"

I need to restrict an (support) user from viewing columns in a table (other users should have full access to this table).
So I granted access to only the columns I specified via "GRANT SELECT ON dbo.TestTable (FirstCol, SecondCol, ThirdCol) TO HR_Intern;"
But when I am running a "SELECT * FROM dbo.TestTable;" i got an Access Denied Error for every other column in the table.
The user is doing customer support using the MSSQL Management Studio directly on the database and the errors won't allow the user to edit the data.
Is it possible to just display the columns the user have access to and ignoring every denied column?
Thanks for your help :)
Better to create a VIEW and provide the users access to it. In the VIEW only those columns these users can see should be part of SELECT statement.
As pointed out by others, you need to replace * by an explicit select list.
In case you are worried about having to specify things twice, here is a query to retrieve the list of permitted columns from metadata.
If you like, you can use its result set to generate (part of) the select list for the query on TestTable.
SELECT c.name
FROM sys.columns c
INNER JOIN sys.database_permissions p
ON p.class = 1
AND p.major_id = c.object_id
AND p.minor_id = c.column_id
AND p.state = 'G'
AND p.grantee_principal_id = DATABASE_PRINCIPAL_ID('HR_Intern')
WHERE c.object_id = OBJECT_ID('dbo.TestTable')
Replace DATABASE_PRINCIPAL_ID('HR_Intern') by DATABASE_PRINCIPAL_ID() to get metadata for the currently active user.
The query is still pretty crude; it disregards table-wide grants, and all denies. You may want to experiment with that a bit.
No. That is how security works in SQL. Basically "SELECT *" is not good form, one is supposed to provide a field list.
If the result set would magically change based on the user logged in that would result in a lot of crappy bug reports because applications would suddenly not work. You asked for all fields, that can not be sent, hence an error report.
One workaround is to have a view with a limited number of fields and direct this user to use the views. Obviously that costs time and attention during development.

SQL Query from SQL novice

I am trying to generate several spreadsheets, sourcing the data from an SQL database. I am new to SQL. The only tool I have for accessing the database is MS Query.
I have managed a lot by the copy & modify process, but now am stuck. I have the following code which allows me to select values from a specified Ac for a specified period.
SELECT Table1.Date, Table1.Ac, Table1.Ref, Table1.Text, Table1.Value
FROM Main.dbo.Table1 Table1
WHERE (Table1.Ac=?) AND (Table1.Date>=? And Table1.Date<=?)
ORDER BY Table1.Date
What I now want to do is:
Delete the Table1.Ac criterium so that I get all records between selected dates
Group by the Table1.Ac field, sorted ascending
In a new column, Display the sum of all the values for each Table1.Ac
This would be very similar to a Summary TB in accounts parlance
As soon as I start modifying the code, I get the message: Parameters are not allowed in queries that can't be displayed graphically.
I would appreciate any help on the SQL code, and on any better tools that I can integrate into Excel. The company is standardising on SQL and converting all its old databases (Access, Accounts, Btrieve, etc) into SQL
I'd recommend working in SQL Server Management Studio if using Microsoft SQL Server.
Does this query suffice?
SELECT Table1.Ac, Sum(Table1.Value)
FROM Main.dbo.Table1 Table1
WHERE (Table1.Date>=? And Table1.Date<=?)
ORDER BY Table1.Date GROUP BY Table1.Ac
Here's a link outlining using MS Query to get data into Excel..
http://office.microsoft.com/en-gb/excel-help/use-microsoft-query-to-retrieve-external-data-HA010099664.aspx

Is there a "Code Coverage" equivalent for SQL databases?

I have a database with many tables that get used, and many tables that are no longer used. While I could sort through each table manually to see if they are still in use, that would be a cumbersome task. Is there any software/hidden feature that can be used on a SQL Server/Oracle database that would return information like "Tables x,y,z have not been used in the past month" "Tables a,b,c have been used 17 times today"? Or possibly a way to sort tables by "Date Last Modified/Selected From"?
Or is there a better way to go about doing this? Thanks
edit: I found a "modify_date" column when executing "SELECT * FROM sys.tables ORDER BY modify_date desc", but this seems to only keep track of modifications to the table's structure, not its contents.
replace spt_values with the tablename you are interested in, the query will give the the last time it was used and what it was used by
From here: Finding Out How Many Times A Table Is Being Used In Ad Hoc Or Procedure Calls In SQL Server 2005 And 2008
SELECT * FROM(SELECT COALESCE(OBJECT_NAME(s2.objectid),'Ad-Hoc') AS ProcName,execution_count,
(SELECT TOP 1 SUBSTRING(s2.TEXT,statement_start_offset / 2+1 ,
( (CASE WHEN statement_end_offset = -1
THEN (LEN(CONVERT(NVARCHAR(MAX),s2.TEXT)) * 2)
ELSE statement_end_offset END) - statement_start_offset) / 2+1)) AS sql_statement,
last_execution_time
FROM sys.dm_exec_query_stats AS s1
CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS s2 ) x
WHERE sql_statement like '%spt_values%' -- replace here
AND sql_statement NOT like 'SELECT * FROM(SELECT coalesce(object_name(s2.objectid)%'
ORDER BY execution_count DESC
Keep in mind that if you restart the box, this will be cleared out
In Oracle you can use the ASH (Active Session History) to find info about SQL that was used. You can also perform code coverage tests with the Hierarchical profiler, where you can find which parts of the stored procedures is used or not used.
If you wonder about the updates on table data, you can also use DBA_TAB_MODIFICATIONS. This shows how many inserts, updates, deletes are done on a table or table partition. As soon as new object statistics are generated, the row for the specified table is removed from DBA_TAB_MODIFICATIONS. You still have help here, since you could also have a peek in the table statistics history. This does not show anything about tables that are queried only. If you really need to know about this, you are to use the ASH.
Note, for both ASH and statistics history access, you do need the diagnostics or tuning pack license. (normally you would want this anyway).
If you use trigger you can detect update insert or delete on table.
Access is problably more difficult.
I use a combination of static analysis in the metadata to determine tables/columns which have no dependencies and runtime traces in SQL Server to see what activity is happening.
Some more queries that might be useful for you.
select * from sys.dm_db_index_usage_stats
select * from sys.dm_db_index_operational_stats(db_id(),NULL,NULL,NULL)
select * from sys.sql_expression_dependencies /*SQL Server 2008 only*/
The difference betweeen what the first 2 DMVs report is explained well in this blog post.
Ed Elliott's open source tool, SQL Cover, is a good bet and has built-in support for the popular unit testing tool, tSQLt.