Query Path to SQL Server Log Files (SSRS / SSAS) - tsql

I need to write a tsql script / procedure, that reads from the SSRS / SSAS / MSSQL Logs.
So fare getting the location of the SQL Errorlog ist easy (SELECT SERVERPROPERTY('ErrorLogFileName') ).
What about the Location for SSRS / SSAS? The script will be executed on many different Servers and I know, that most of them don't use the default location for their SQL Server Instances (i.e. C:\Program Files....). Is there any way to get this paths in tsql?
Cheers
Kim

Ok, I found a way. Don't know if that is the best way, but it's fast and works on all my instances. Below code for the SSRS Path. SSAS works similarly.
DECLARE #InstanceName [nvarchar] (128)
,#SSRSInstanceName [nvarchar] (128)
,#RegPathSSRS [nvarchar] (256)
,#DirPathSSRS [nvarchar] (256)
SET #InstanceName = COALESCE(CONVERT([nvarchar](100), SERVERPROPERTY('InstanceName')), 'MSSQLSERVER');
IF #InstanceName != 'MSSQLSERVER'
BEGIN
SET #InstanceName = #InstanceName
END
EXEC [master]..[xp_regread] N'HKEY_LOCAL_MACHINE'
,N'Software\Microsoft\Microsoft SQL Server\Instance Names\RS'
,#InstanceName
,#SSRSInstanceName OUTPUT;
SET #RegPathSSRS = N'Software\Microsoft\Microsoft SQL Server\'+#SSRSInstanceName+'\Setup';
EXEC [master]..[xp_regread] N'HKEY_LOCAL_MACHINE'
,#RegPathSSRS
,'SQLPath'
,#DirPathSSRS OUTPUT;
You will now find the Path to the ReportServer Logs as:
#DirPathSSRS + '\LogFiles'

Related

Get all database names from multiple servers

We have multiple SQL Servers and most of them are standalone. I am in need of creating a stored procedure / view that would insert all database names into a table from all servers.
Is there a way to do this via a stored procedure or a view? I do not have any powershell or .Net experience.
Here's what I have so far. I just can't figure out how to 'jump' from server to server and add all my results into a real table.
CREATE TABLE ##temp
(
DATABASE_NAME VARCHAR(100),
DATABASE_SIZE INT,
REMARKS VARCHAR(500)
)
INSERT into ##temp
EXEC [sp_databases]
--doing this to also get ServerName along with the db name.
--When I insert into a real table, I'll seperate it into two columns plus remove "#_!_#"
update ##temp
set DATABASE_NAME = (select ##SERVERNAME ) + '#_!_# ' + DATABASE_NAME
where DATABASE_NAME not like '%#_!_#%'
select DATABASE_NAME from ##temp
SQL Server Management Studio allows you to execute a query against multiple servers using the Registered Servers feature. This was added in SQL Server 2008 as this tutorial shows so you shouldn't worry about compatibility.
Running multi-server queries is easy:
From the View menu, select `Registered Servers. This will open a new window similar to the Object Explorer that displays the objects of a single server.
Add connections for all your servers connection details in the Local Server Groups folder
Right-click on the Local Server Groups folder and select New Query. The query you enter here will run an all registered servers.
To find all databases run select * from sys.databases or just sp_databases
SSMS will collect the results from all servers and display them in a grid. If you want the results to go to a single server's table though, you'll have to add the target server as a linked server to all others and use a four-part name to target the target table, eg INSERT INTO myManagementServer.MyDb.dbo.ThatTable...
SQL Server has even more powerful features for managing multiple servers. You can administer multiple servers through a Central Management Server and apply settings to multiple servers through policies. That feature was also added in 2008.
In SQL Server 2008 R2 the SQL Server Utility was added which goes even farther and collects diagnostics, metrics, performance data from multiple servers and stores it in a management warehouse for reporting. Imagine being able to see eg storage and query performance for multiple servers, or free space trends for the last X months.
The drawbacks are that historical data needs space. Collecting it also requires adding some stored procedures to all monitored servers, although this is done automatically.
For this kind of thing it's good to have at least one server that has a linked connection to all the servers you need information for. If you do then you can use this little script I just wrote:
-- (1) Create global temp table used to store results
IF OBJECT_ID('tempdb..##databases') IS NOT NULL DROP TABLE ##databases;
CREATE TABLE ##databases
(
serverDBID int identity,
serverName varchar(100),
databaseName varchar(100),
databaseSize decimal(20,6)
);
-- (2) Create and populate table variable used to collect server names
DECLARE #servers TABLE(id int identity, serverName varchar(100));
INSERT #servers(serverName)
SELECT name FROM sys.servers;
-- (3) loop through each DB and collect database names into ##databases
DECLARE #i int = 1, #serverName varchar(100), #db varchar(100), #sql varchar(8000);
WHILE #i <= (SELECT COUNT(*) FROM #servers)
BEGIN
SELECT #serverName = serverName FROM #servers WHERE id = #i;
SET #sql = 'INSERT ##databases(serverName, databaseName) SELECT '''+#serverName+
''', name FROM master.sys.databases';
EXEC (#sql);
SET #i += 1;
END;
-- (4) Collect database sizes
SET #i = 1; -- reset/re-use #i;
WHILE #i <= (SELECT COUNT(*) FROM ##databases)
BEGIN
SELECT #serverName = serverName, #db = databaseName
FROM ##databases
WHERE serverDBID = #i;
SET #sql =
'UPDATE ##databases
SET databaseSize =
(SELECT sum(size)/128. FROM ['+#serverName+'].['+#db+'].sys.database_files)
WHERE serverDBID = '+CAST(#i AS varchar(4))+';'
BEGIN TRY
EXEC (#sql);
END TRY
BEGIN CATCH
PRINT 'There was an error getting dbsize info for '+#serverName+' > '+#db;
END CATCH;
SET #i += 1;
END;
-- Final Output
SELECT * FROM ##databases;

T-Sql USE command: how to handle errors?

I run a script which SELECTs data from several databases on the same server.
USE db1
SELECT x from tbl1
USE db2
SELECT y from tbl2
... etc.
If one of the databases is being restored from a backup, the script errors out on the USE statement. How can I handle these errors? TRY - CATCH doesn't work.
This is on 2008R2.
Edit: The error returned is:
Msg 927, Level 14, State 2, Line 4
Database 'db2' cannot be opened. It is in the middle of a restore.
You can obtain the current status of a database using DATABASEPROPERTYEX:
SELECT DATABASEPROPERTYEX('db_name', 'Status')
This will output the current status of your database, which will include whether it is restoring (which will give a status of 'RESTORING').
Before executing your USE, do the following:
DECLARE #Status SQL_VARIANT
SELECT #Status = DATABASEPROPERTYEX('db1', 'Status')
IF (#Status = 'ONLINE')
BEGIN
USE db1
-- Do stuff
END
ELSE
BEGIN
-- Do other stuff
END

TSQL call query from wtihin a query in same database

I am blaming this on Monday morning, but is there some way to run a query from within a query.....
Isn't there some sort of command like
EXEC sp_ myOtherQuery.sql
I realize this lacks all sorts of error handling just wondering if there was some way to do this.
I had similar situation and used something like:
declare #cmd nvarchar(max)
declare #spname nvarchar(256)
set #spname=<your_database_name> + '.dbo.' + 'sp_executesql'
set #cmd='your query text'
execute #spname #cmd
If you're doing this in SQL Server Management Studio:
Turn on SQLCMD mode using the query menu. Then use the :r directive to include the other sql file into the one you're editing.
--sql statements
:r "C:\Full\Path\To\Sql\File.sql"
--More sql statements
This is effectively an include directive. The contents of the sql file will be inserted in your script at run time and the whole thing will be run as one.
This works only in SSMS. It isn't something you can do in a stored procedure.

Query referencing aliased column in order by in SQLServer 2012

I have a SQL Select query that's embedded in a piece of C# code which I don't want to change. My problem is that the query executes fine on SQLServer 2008 but not 2012.
The offending line of code is:
Select code as SiteCode from TimeSheetContracts S order by S.SiteCode
Executed in a database on SQL2008 it works fine. The same database upgraded to SQLServer 2012 errors with the following...
Msg 207, Level 16, State 1, Line 2
Invalid column name 'SiteCode'.
If I edit the query to be
Select code as SiteCode from TimeSheetContracts S order by SiteCode
it works fine. Can anyone explain this?
There is no column in TimeSheetContracts called SiteCode, so a reference to s.SiteCode is not valid. Aliasing in ORDER BY is a little more strict since SQL Server 2000, when the syntax was a little more forgiving. The only way s.SiteCode would have worked on your SQL Server 2008 instance was if your database was in COMPATIBILITY_LEVEL = 80 (go ahead and try it on a different database that is 90 or greater). Once you move to SQL Server 2012, 80 is no longer an option. On a 2005, 2008 or 2008 R2 instance, try this:
CREATE DATABASE floob;
GO
USE floob;
GO
CREATE TABLE dbo.SalesOrderHeader(SalesOrderID INT);
GO
SELECT SalesOrderID AS ID FROM dbo.SalesOrderHeader AS h ORDER BY h.ID; -- fails
GO
ALTER DATABASE floob SET COMPATIBILITY_LEVEL = 80;
GO
SELECT SalesOrderID AS ID FROM dbo.SalesOrderHeader AS h ORDER BY h.ID; -- works
GO
USE master;
GO
DROP DATABASE floob;
If you want to use the column alias, you'll need to (and should always have been) just use the alias. If you want to use the table alias prefix, you'll need to use s.code.

How do I select from a stored procedure in Sybase?

My DBA has constructed me a stored procedure in a Sybase database, for which I don't have the definition.
If I run it, it returns a resultset with a set of columns and values. I would like to SELECT further to reduce the rows in the result set. Is this possible?
From this question it seems like I could insert the results into a temporary table, but I'm not sure I've got permissions to do this.
Is there any way I can SELECT certain rows, or if not, can someone give me example code for simulating with a temporary table?
In Sybase ASE, we can use this hack to select from a stored procedure via a "proxy table":
http://www.sypron.nl/proctab.html
Example:
sp_addserver loopback, null, ##servername
go
create existing table
sp_test12 (
Document_Name varchar(100),
Required_Status varchar(5),
Doc_ID varchar(10),
OrderBy int,
No_of_Copy_Retain int,
_p_EPEB_ID varchar(10) null,
_p_MY_NAME varchar(3) null,
_p_MY_NO varchar(10) null,
_p_EPEB_EDATE datetime null,
_TXN varchar(10) null,
_SUBTXN varchar(15) null,
_OwnType_ID1 varchar(5) null,
_OwnType_ID2 varchar(5) null,
_blnflag int null
)
external procedure
at 'loopback.MYDB.dbo.usp_xyz'
go
select
Doc_ID, No_of_Copy_Retain, _p_EPEB_ID, _p_EPEB_ID, _p_MY_NAME, _p_MY_NO
from #sp_test12
where
_p_EPEB_ID='EPEB1508'
and _p_MY_NAME='107'
and _p_MY_NO='2011000045'
and _p_EPEB_EDATE='2011-01-15 15:03:03.0'
and _TXN='TX012'
and _SUBTXN='TX012.001'
and _OwnType_ID1='ASSN'
and _OwnType_ID2='ASSN'
and _blnflag=0
go
Under Sybase IQ (12.6 and higher at least) you can select from a stored procedure and filter the results as if it was a table. I do not know if this works under ASE or ASA but you could give it a try.
So if you stored procedure is called myproc an the result set has a column ACTIVE which can be either 0 or 1 and you want to select only the ACTIVE = 1 rows you could do this.
SELECT * FROM myproc() WHERE ACTIVE = 1
Under IQ you can also use this as a derived table and JOIN it with other tables for example like this...
SELECT t1.name,t1.address,t2,active
FROM tbl_atable t1,
( SELECT * FROM myproc() WHERE ACTIVE = 1) t2
WHERE t1.active = t2.active
...which is kind of neat!
I hope that works for which ever version of Sybase you are running.
You will need to ask the DBA to change the stored procedure.
You could get it changed to select the results into a temporary table rater than a plain select and then you can write your own select on that temp table to return only the rows you want
It is possible with ASE but in a rather roundabout kind of way using CIS and proxy tables. The mechanism is described very well on Rob Verschoor's site:
http://www.sypron.nl/proctab.html
I tried it out once as a curiosity and indeed it does work. I did not delve into the tricky question of error-handling.
pjjH
As far as I know, this is not possible in Sybase ASE. Even using
insert #temp_table
exec my_procedure
doesn't work (at least on sybase 12.x).
Just a thought.
Perhaps your DBA could prepare a view instead of a stored procedure, if he wanted you for some reason not to look at the inner stuff or worry about it.
Another approach would be to see the stored procedure text (unless encrypted) with sp_helptext and rewrite it for your own purposes (eg. into a view) to be able to apply additional conditioning to the resultset.
In Sybase IQ, you can do this:
select < col1>, < col2> from < sp_name>('< sp_arg>') where < predicate>
Example:
select Object, DbspaceName, ObjSize from sp_iqindexinfo ('table xyz') where Object like '%col1_indx%'