Blog Home  Home RSS 2.0 Atom 1.0 CDF  
some thoughts... - August, 2006
IT makes the world go round - and sometimes stops it...
 
 Sunday, August 27, 2006

Brett Kaiser has posted a article called "How do I track data changes in a database" including his real usefull coding about his idea of doing this via T-SQL automatically every time a DELETE or UPDATE Modification will be executed.

The following content is intellectual property of Brett Kaiser, the original posting can be found here:

USE Northwind
SET NOCOUNT ON
GO

-- For example purposes, create a sample tables
CREATE TABLE myTable99(Col1 int IDENTITY(1,1), Col2 char(1), Col3 datetime DEFAULT(GetDate()), Col4 decimal(5,2))
CREATE TABLE x002548.myTable99(Col1 int IDENTITY(1,1), Col2 char(1), Col3 datetime DEFAULT(GetDate()), Col4 decimal(5,2))
GO

-- Give the sample tables some data
INSERT INTO myTable99(Col2, Col4)
SELECT 'x', 1 UNION ALL SELECT 'y', 2 UNION ALL SELECT 'z', 3
INSERT INTO x002548.myTable99(Col2, Col4)
SELECT 'a', 24 UNION ALL SELECT 'b', 25 UNION ALL SELECT 'c', 26

--Lets have a look
SELECT 'x002548' AS Source, * FROM x002548.myTable99
UNION ALL
SELECT 'dbo' AS Source, * FROM myTable99
GO

-- CREATE A Driver Table for all Tables in your catalog you wish to audit
CREATE TABLE myAudit99(TABLE_CATALOG sysname, TABLE_SCHEMA sysname, TABLE_NAME sysname)
GO

-- Populate the audit driver table with the table you want...you can use any type of process for this
INSERT INTO myAudit99(TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME)
SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_NAME LIKE 'myTable99%'

-- Lets create some audit tables based on the Driver

DECLARE myCursor99 CURSOR
FOR
SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME
FROM myAudit99

DECLARE @TABLE_CATALOG sysname, @TABLE_SCHEMA sysname, @TABLE_NAME sysname, @COLUMN_NAMES varchar(8000), @sql varchar(8000)
SELECT @COLUMN_NAMES = ''
OPEN myCursor99

FETCH NEXT FROM myCursor99 INTO @TABLE_CATALOG, @TABLE_SCHEMA, @TABLE_NAME

WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @SQL = 'CREATE TABLE ' + @TABLE_CATALOG + '.' + @TABLE_SCHEMA + '.' + @TABLE_NAME + '_H ('
+ ' HIST_ADD_DT datetime DEFAULT (getDate()), HIST_ADD_TYPE char(1) NOT NULL'
+ ', HIST_ADD_SYSTEM_USER sysname NOT NULL, HIST_ADD_USER_NAME sysname NOT NULL'
+ ', HIST_ADD_HOSTNAME sysname NOT NULL, HIST_ADD_SPID int NOT NULL, HIST_ADD_DESC varchar(50) '
, @COLUMN_NAMES = @COLUMN_NAMES + ', ' + COLUMN_NAME
+ ' ' + DATA_TYPE
+ CASE WHEN CHARACTER_MAXIMUM_LENGTH IS NOT NULL THEN '(' + CONVERT(varchar(20),CHARACTER_MAXIMUM_LENGTH) + ')'
WHEN DATA_TYPE = 'decimal' THEN '(' + CONVERT(varchar(20),NUMERIC_PRECISION) + ','
+ CONVERT(varchar(20),NUMERIC_SCALE) + ')'
ELSE ''
END
FROM INFORMATION_SCHEMA.Columns
WHERE TABLE_CATALOG = @TABLE_CATALOG AND TABLE_SCHEMA = @TABLE_SCHEMA AND TABLE_NAME = @TABLE_NAME
ORDER BY ORDINAL_POSITION

SELECT @SQL = @SQL + @COLUMN_NAMES + ')'

EXEC(@SQL)

SELECT @SQL = '', @COLUMN_NAMES = ''

FETCH NEXT FROM myCursor99 INTO @TABLE_CATALOG, @TABLE_SCHEMA, @TABLE_NAME

END

CLOSE myCursor99
DEALLOCATE myCursor99
GO

SELECT *
FROM INFORMATION_SCHEMA.Columns
WHERE TABLE_NAME Like 'myTable99%'
ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION

-- Now Lets create the audit TRIGGERS

DECLARE myCursor99 CURSOR
FOR
SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME
FROM myAudit99

DECLARE @TABLE_CATALOG sysname, @TABLE_SCHEMA sysname, @TABLE_NAME sysname, @COLUMN_NAMES varchar(8000), @sql varchar(8000)
SELECT @COLUMN_NAMES = ''
OPEN myCursor99

FETCH NEXT FROM myCursor99 INTO @TABLE_CATALOG, @TABLE_SCHEMA, @TABLE_NAME

WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @COLUMN_NAMES = @COLUMN_NAMES + ', ' + COLUMN_NAME
FROM INFORMATION_SCHEMA.Columns
WHERE TABLE_CATALOG = @TABLE_CATALOG AND TABLE_SCHEMA = @TABLE_SCHEMA AND TABLE_NAME = @TABLE_NAME
ORDER BY ORDINAL_POSITION

SELECT @SQL = 'CREATE TRIGGER ' + @TABLE_SCHEMA + '_' + @TABLE_NAME + '_TR ON ' + @TABLE_SCHEMA + '.' +@TABLE_NAME
+ ' FOR UPDATE, DELETE AS '
+ ' DECLARE @HOSTNAME sysname, @DESC varchar(50) '
+ ' SELECT @HOSTNAME = hostname from master.dbo.sysprocesses where spid = @@SPID '
+ ' IF EXISTS(SELECT * FROM ' + @TABLE_NAME + ') SELECT @DESC = '
+ '''' + '''' + ' ELSE SELECT @DESC = ' + '''' + 'MASS DELETE' + ''''
+ ' If Exists (Select * From Inserted) And Exists (Select * From Deleted) '
+ ' INSERT INTO ' + @TABLE_NAME + '_H ( '
+ ' HIST_ADD_TYPE, HIST_ADD_SYSTEM_USER, HIST_ADD_USER_NAME, HIST_ADD_HOSTNAME, HIST_ADD_SPID, HIST_ADD_DESC'
+ @COLUMN_NAMES + ')'
+ ' SELECT ''U'', SYSTEM_USER, USER_NAME(), @HOSTNAME, @@SPID, @DESC'
+ @COLUMN_NAMES + ' FROM deleted'
+ ' If Not Exists (Select * From Inserted) And Exists (Select * From Deleted) And @DESC = '''' '
+ ' INSERT INTO ' + @TABLE_NAME + '_H ( '
+ ' HIST_ADD_TYPE, HIST_ADD_SYSTEM_USER, HIST_ADD_USER_NAME, HIST_ADD_HOSTNAME, HIST_ADD_SPID, HIST_ADD_DESC'
+ @COLUMN_NAMES + ')'
+ ' SELECT ''D'', SYSTEM_USER, USER_NAME(), @HOSTNAME, @@SPID, @DESC'
+ @COLUMN_NAMES + ' FROM deleted'
+ ' If Not Exists (Select * From Inserted) And Exists (Select * From Deleted) And @DESC <> '''' '
+ ' INSERT INTO ' + @TABLE_NAME + '_H ( '
+ ' HIST_ADD_TYPE, HIST_ADD_SYSTEM_USER, HIST_ADD_USER_NAME, HIST_ADD_HOSTNAME, HIST_ADD_SPID, HIST_ADD_DESC'
+ @COLUMN_NAMES + ')'
+ ' SELECT TOP 1 ''D'', SYSTEM_USER, USER_NAME(), @HOSTNAME, @@SPID, @DESC'
+ @COLUMN_NAMES + ' FROM deleted'

EXEC(@SQL)

SELECT @SQL = '', @COLUMN_NAMES = ''

FETCH NEXT FROM myCursor99 INTO @TABLE_CATALOG, @TABLE_SCHEMA, @TABLE_NAME

END

CLOSE myCursor99
DEALLOCATE myCursor99
GO

-- Now let's pretend to be an ignorant boss...not to much of a stretch there....

UPDATE myTable99 SET Col2 = 'G'

SELECT * FROM myTable99_H

DELETE FROM myTable99 WHERE Col1 = 1

SELECT * FROM myTable99_H

DELETE FROM x002548.myTable99

SELECT * FROM x002548.myTable99_H

SELECT * FROM myTable99

SELECT * FROM x002548.myTable99
GO

SET NOCOUNT OFF
DROP TABLE myAudit99
DROP TRIGGER dbo_myTable99_TR
DROP TRIGGER x002548_myTable99_TR
DROP TABLE dbo.myTable99
DROP TABLE x002548.myTable99
DROP TABLE dbo.myTable99_H
DROP TABLE x002548.myTable99_H
GO

Sunday, August 27, 2006 3:09:14 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |  |  |   | 
Nigel Rivett has published an interesting detailed article about common table expressions in SQL Server 2005 on simple-talk.com.
Sunday, August 27, 2006 2:39:40 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |  |   | 

Grant Robinson has developed an interesting online-game, which can be found via the project site.

All you have to do is to launch the project and guess the search term which could have brought up the pictures shown on the screen.

Nice game - if you like it too think about donating...

Sunday, August 27, 2006 2:32:19 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |   | 
 Friday, August 25, 2006

Definition from the SQL Server 2005 Product Guide:

"SQL Server Management Objects (SMO) is the management object model for SQL Server 2005. SMO represents significant design and architectural improvements for the SQL Server management object model. It is a simple to use but rich object model that is based on .NET Framework managed code. SMO is the primary tool for developing database management applications using the .NET Framework. SMO is used extensively by SQL Server Management Studio. Every administrative action that you can perform in SQL Server Management Studio, you can also accomplish by using SMO.
The new SMO object model and the WMI APIs replace SQL-DMO. Where possible, SMO incorporates similar objects as those in SQL-DMO for ease of use. You can still use SQL Server 2005 with SQL-DMO, but SQL-DMO will not be updated to manage features that are specific to SQL Server 2005.

Microsoft SQL Server 2005 Management Objects Collection from the Feature Pack for Microsoft SQL Server 2005 - April 2006

Database Engine Administration Programming

SQL Server Management Objects (SMO)

Programming Specific Tasks

Microsoft.SqlServer.Management.Smo.Agent Namespace

Job.Start Method

Job.CurrentRunStatus Property

Jasper Smith - Getting Started with SMO in SQL 2005

Darshan Singh - A Quick Introduction to SQL Server Management Objects (SMO)

Thomas Haller - SMO - Manage your SQL Server

Michiel Wories - SQL Server: SMO Scripting Basics

SMO enumerator in SQL Server Integration Services

Friday, August 25, 2006 2:55:09 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |  |  |   | 

Randy Dyess has published an article called "Auditing Your SQL Server Environment: Part II (Reviewing Role Memberships)"

The following content is intellectual property of Randy Dyess, the original posting can be found here:

"Roles should be in foremost in your mind when planning the security of your SQL Server environments. Auditing inherited SQL Server installations is a relatively easy thing to accomplish, and all DBAs should audit their environment and create documentation if they have not already done so. Once you can document the logins assigned to each of your fixed and user-defined roles, you can start to remove any duplication of permissions which can reduce the time needed to troubleshoot future permission errors."

--Use the master database
USE master
go

IF OBJECT_ID('dbo.spRoleMembers') IS NOT NULL
DROP PROCEDURE dbo.spRoleMembers
GO

CREATE PROCEDURE dbo.spRoleMembers
AS
/************************************************************
Creation Date: 04/28/02 Created By: Randy Dyess
Web Site: www.TransactSQL.Com
Email: RandyDyess@TransactSQL.Com
Purpose: Loops through all databases and obtains member
for database roles as well as server role members.
Location: master database
Output Parameters: None
Return Status: None
Called By: None
Calls: None
Data Modifications: None
Updates:
None

************************************************************/

SET NOCOUNT ON

--Variables
DECLARE @lngCounter INTEGER
DECLARE @strDBName VARCHAR(50)
DECLARE @strSQL NVARCHAR(4000)

--Temp table to hold database and user-define role user names
CREATE TABLE #tRolemember
(
strServerName VARCHAR(50) DEFAULT @@SERVERNAME
,strDBName VARCHAR(50)
,strRoleName VARCHAR(50)
,strUserName VARCHAR(50)
,strUserID VARCHAR(100)
)

--Temp table to hold database names
CREATE TABLE #tDBNames
(lngID INTEGER IDENTITY(1,1)
,strDBName VARCHAR(50)
)

--Create permanent table
IF OBJECT_ID ('dbo.tRolemember') IS NULL
BEGIN
CREATE TABLE dbo.tRolemember
(
strServerName VARCHAR(50)
,strDBName VARCHAR(50)
,strRoleName VARCHAR(50)
,strUserName VARCHAR(50)
,strUserID VARCHAR(100)
)
END

--Obtain members of each server role
INSERT INTO #tRolemember (strRoleName, strUserName, strUserID)
EXEC dbo.sp_helpsrvrolemember

--Obtain database names
INSERT INTO #tDBNames (strDBName)
SELECT name FROM master.dbo.sysdatabases
SET @lngCounter = @@ROWCOUNT

--Loop through databases to obtain members of database roles and user-defined roles
WHILE @lngCounter > 0
BEGIN

--Get database name from temp table
SET @strDBName = (SELECT strDBName FROM #tDBNames WHERE lngID = @lngCounter)

--Obtain members of each database and user-defined role
SET @strSQL = 'INSERT INTO #tRolemember (strRoleName, strUserName, strUserID)
EXEC '
+ @strDBName + '.dbo.sp_helprolemember'

EXEC sp_executesql @strSQL

--Update database name in temp table
UPDATE #tRolemember
SET strDBName = @strDBName
WHERE strDBName IS NULL

SET @lngCounter = @lngCounter - 1

END

--Place data into permanent table
INSERT INTO tRolemember
SELECT trm.* FROM #tRolemember trm
LEFT JOIN tRoleMember prm
ON trm.strUserName = prm.strUserName
AND trm.strDBName = prm.strDBName
AND trm.strRoleName = prm.strRoleName
AND trm.strServerName = prm.strServerName
WHERE prm.strServerName IS NULL

GO

--Test Stored Procedure
EXEC dbo.spRoleMembers

PRINT 'Display by User'
SELECT strUserName, strDBName, strRoleName, strServerName FROM tRolemember
WHERE strUserName <> 'dbo'
ORDER BY strUserName

PRINT 'Display by Role'
SELECT strRoleName, strDBName, strUserName,strServerName FROM tRolemember
WHERE strUserName <> 'dbo'
ORDER BY strRoleName

PRINT 'Display by Database'
SELECT strDBName, strRoleName,strUserName, strServerName FROM tRolemember
WHERE strUserName <> 'dbo'
ORDER BY strDBName


Randy also has published a script about auditing user's passwords

The following content is intellectual property of Randy Dyess, the original posting can be found here:

IF OBJECT_ID('dbo.spAuditPasswords') IS NOT NULL
DROP PROCEDURE dbo.spAuditPasswords
GO

CREATE PROCEDURE dbo.spAuditPasswords
AS
/****************************************************************************
Creation Date: 03/22/02 Created By: Randy Dyess
Web Site: www.TransactSQL.Com
Email: RandyDyess@TransactSQL.Com
Purpose: Perform a simple audit of user's passwords
Location: master database
Output Parameters: None
Return Status: None
Called By: None
Calls: None
Data Modifications: None
Updates: None
Date Author Purpose
---------- -------------------------- ---------------------------------
****************************************************************************/

SET NOCOUNT ON

--Variables
DECLARE @lngCounter INTEGER
DECLARE @lngCounter1 INTEGER
DECLARE @lngLogCount INTEGER
DECLARE @strName VARCHAR(256)

--Create table to hold SQL logins
CREATE TABLE #tLogins
(
numID INTEGER IDENTITY(1,1)
,strLogin SYSNAME NULL
,lngPass INTEGER NULL
)

--Insert non ntuser into temp table
INSERT INTO #tLogins (strLogin)
SELECT name FROM master.dbo.syslogins WHERE isntname = 0
SET @lngLogCount = @@ROWCOUNT

--Determine if password is null and user iis SQL Login
PRINT 'The following logins have blank passwords'
SELECT name AS 'Login Name' FROM master.dbo.syslogins
WHERE password IS NULL
AND isntname = 0


--Determine if password and name are the ssame
SET @lngCounter = @lngLogCount

WHILE @lngCounter <> 0
BEGIN
    SET @strName = (SELECT strLogin FROM #tLogins WHERE numID = @lngCounter)

    UPDATE #tLogins
    SET lngPass = (SELECT PWDCOMPARE (@strName,(SELECT password FROM master.dbo.syslogins WHERE name = @strName)))
    WHERE numID = @lngCounter

    SET @lngCounter = @lngCounter - 1
END

PRINT 'The following logins have passwords the same as their login name'
SELECT strLogin AS 'Login Name' FROM #tLogins WHERE lngPass = 1

--Reset column for next password test
UPDATE #tLogins
SET lngPass = 0

--Determine if password is only one characcter long
SET @lngCounter = @lngLogCount

WHILE @lngCounter <> 0
BEGIN
    SET @lngCounter1 = 1
    SET @strName = (SELECT strLogin FROM #tLogins WHERE numID = @lngCounter)
    WHILE @lngCounter1 < 256
    BEGIN
        UPDATE #tLogins
        SET lngPass = (SELECT PWDCOMPARE (CHAR(@lngCounter1),(SELECT password FROM master.dbo.syslogins WHERE name = @strName)))
        WHERE numID = @lngCounter
        AND lngPass <> 1
        
        SET @lngCounter1 = @lngCounter1 + 1
    END

    SET @lngCounter = @lngCounter - 1
END

PRINT 'The following logins have one character passwords'
SELECT strLogin AS 'Login Name' FROM #tLogins WHERE lngPass = 1
GO

--Test
EXEC dbo.spAuditPasswords


And last but not least Bradley Morris has published an article about "How to Script User and Role Object Permissions in SQL Server"

Friday, August 25, 2006 2:19:02 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |  |  |   | 
 Thursday, August 24, 2006

Ever tried to export data from Sharepoint 2003 to Excel spreadsheet like described in this article?

Have you also discovered that exporting a rating scale would not work correctly?

Microsoft provides an appropriate KB-article (889591), which tellingly is called:
"Survey results in SharePoint Portal Server 2003 and in Windows SharePoint Services are not exported to an Excel workbook if the answer to a question uses a rating scale".

Thursday, August 24, 2006 6:11:01 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [1]   |   | 
 Thursday, August 17, 2006

You need to have to do some manual prerequisites to convince you Reporting Services installation to accept SSIS packages as a source as described in "Defining Report Datasets for Package Data from SQL Server Integration Services".

Russell Christopher brings up some additional thoughts in his article "Using a parameterized SSIS package as a data source for SQL Reporting Services" and therefor lifts this datasource to a higher level with more value.

Thanks Russell!

Thursday, August 17, 2006 12:23:04 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |  |   | 
 Wednesday, August 16, 2006

You probably know that PASS Germany publishes a really sophisticated newsletter every month containing a load of useful informations regarding every topic of the SQL Server.

Because of being the German chapter they are all in German of course... :-)

You want to find this newsletter regularly in your In-box every first day of the month?
Then go and join up and be a member of the German community!

Wednesday, August 16, 2006 12:58:24 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |   | 
 Tuesday, August 15, 2006

After ruining my SDA I had to decide which toy to buy next...

The new mobile should meet the following requirements:

  • synchronize contacts and calender items with my exchange in the way I like
    [I think it is really boring if you have to use your Outlook in the way your mobile manufacturer thinks you should use it...]
  • several profiles for several situations
  • email ability
  • qwertz-keyboard
  • no pen for navigation
  • long lasting accu

I do not need multiple ring tones, a camera, video, MP3 and so on - I have had that on the SDA and I used it only a couple of times...

I decided to buy a Blackberry 8707v, which is a german derivate of this one.

And you probably ask yourself why, especially because of Exchange 2003 bringing up "Exchange Direct Push" in SP2 and the Blackberry solution requiring additional installs and licenses and a seperate fee for the Blackberry service?

Mainly because of Christoph Stotz, being the chairman of the board of PASS Germany, teasing me due to my mail access and some problems in the first days...
Christoph, you will have to answer me some more questions in the future I think... ;-)

As pointed out by Volker Weber in his article the new solution is not a kind of real push-mail...
And RIM now offers BlackBerry Enterprise Server™ Express which is a free solution if you do not need to have more than 15 users.
(probably to tighten the sales regarding products and services, but hey, thats marketing! and a kind of Microsoft style also...)

So I decided that other users should make experiences using Exchange 2003 SP2 or Exchange 2007 and I will decide to jump onboard if I get aware of positive experiences in a year or two... If the Blackberry will live longer than the SDA... :-)

Tuesday, August 15, 2006 10:08:58 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |  |   | 

If you are engaged in the SQL Server community and techniques you probably know Joe Webb as a source of inspiration regarding SQL Server Notification Services [SQLNS].

But Joe does not have only write technical books about SQLNS, he also has written a guidebook for being self-employed called the The Rational Guide to IT Consulting which is pretty usefull and a kind of "Project REAL for self-employed consultants".

Tuesday, August 15, 2006 9:04:21 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |   | 

If you are interested in the post-installation steps required after you successfully have installed SAP BW 3.5 you should have a look at this document of the MyITgroup. They are also offering more interesting documents on other SAP BW topics.

If you have do deal with licensing issues after installing and post-installing I would suggest SAP License (BC-CST-SL) which contains step-by-step descriptions about doing license management via the transaction SLICENSE or via the OS level. Just as a remark: the OS level is usefull if you have forgotten that your license keys will expire, because it is the only chance to connetc to the system while the GUI is not working anymore...

And if you are interested in general informations about SAP licensing you should use this link to the SAP library.

Tuesday, August 15, 2006 6:58:33 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   | 

Mark Miller has shared his experiences on competing against a SAP solution offering in his article SAP the New BI Player .

It seems that I am not the only one who expects that SAP is going to push the Business Warehouse within a short time to engage a new target group - even though they are bundling a bunch of components to SAP Netweaver (including BI, Enterprise Portal and some other interesting applications)...
Sure there are enough SAP core customers which are not using BW at the moment to engage, but MS also is entering the market of SAP core customers with tools and techniques like SQL Server Reporting Services, Biztalk, Performance Point Server and so on. We will have to wait and see...

Mark also mentions the concept of BI Accelerator for high performance analytics and there we both also have the very same opinion:

"They also have the BI Accelerator for high performance analytics (i.e. hardware and extra license fees) to make your large queries respond quickly. Not a one running in Australia yet. My perception is that this is a mistake in product marketing for SAP. It makes it sound like if you have lot of data, you're going have performance problems so you need to invest in additional hardware and we are going charge you an additional license because the one you already bought doesn’t do the job. SAP needs to rethink this."

Sounds very weird, doesn´t it? ;-)

Tuesday, August 15, 2006 6:34:26 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |  |   | 
Russell Christopher has posted a very intersting summary of SharePoint Integration in SQL Server 2005 SP2.
Tuesday, August 15, 2006 6:08:46 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |   | 

Nobody should say that Microsoft and the product teams do not listen to feedback and are not willing to learn...

With SP 1 Microsoft had "killed" the "Select All" Parameter for Multivalue Parameters and thereby triggered many discussions throughout Reporting Services users like this one in Nick Barclay's BI Blog.
There was a workaround provided but this means that many manual work had to be done after SP1 surprisingly suppressed the option "Select All"...

Brian Welcker now has given some explanations and announced that "Select All" Parameter for Multivalue Parameters will be reimplemented in SP2 and if you would like to get it earlier as SP2 arrives you could get in contact with Support Services and refer tor Knowledge Base Article #919478 - which is not published at the moment.

SSRS Team 0 : 1 SSRS Users
I think this will be continued...
:-)

Tuesday, August 15, 2006 5:53:48 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |   | 

Chris Parkes has published a real interesting and detailed article "Are Office Excel 2007 Files Backwards Compatible?" which really is a must-read if you will have a mixed szenario on the day Office 2007 arrives.

Tuesday, August 15, 2006 9:05:39 AM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   | 
 Friday, August 11, 2006

The following content is intellectual property of Brian Keller, the original posting can be found here.

"Report Manager is a solid, Web-based administrative tool for Reporting Services, but it is not the end-all-be-all of administrative functionality for a report server. There are many capabilities available through the Web service that Report Manager does not take advantage of. Case in point: Setting a security policy (otherwise known as a role assignment) for an item using Report Manager is a bit cumbersome, especially if the item for which you want to add a policy is nested several folders deep in your report server namespace. Let's take an example. Let's say you have a folder at “/Budgets/Finance” and you would like to give Bob permission to view reports in the Finance folder. You add a new role assignment for Bob and make him a Browser user of the Finance folder. Bob logs into Report Manager hoping to navigate to the Finance folder, but...Bob is not able to see any folders when he logs in. What gives? Well, unfortunately the path to Bob's Finance folder actually contains three items: The Home or root folder (”/”), the Budgets folder and the Finance folder. Because Bob is not allowed to view the root folder or the Budgets folder, he will never see the Finance folder for which he has permissions. Sorry Bob. In order to give Bob Browser permissions on the Finance folder, you must add Bob as a Browser of both the Home and Budgets folders. If you need to add more groups or users to the Finance folder, it can get downright tiresome. Oh, did I mention that every time you add a policy for Bob to one of the folders, the inherited policy is broken. Yes, that means that any users that enjoyed inherited permissions to those items (for example BUILTIN\Administrators or some other administrator group) no longer have any access rights. You will have to re-add inherited permissions as local policies on each of the three folders in our example. Yikes. Fortunately for Bob, Reporting Services offers rs.exe, a scripting utility with complete access to the Reporting Services Web service. You can use this scripting tool to automate certain tasks and to perform administrative functions that may not be easily automated through Report Manager.

The following sample script can be used to add a security policy for a nested folder or report which automatically gives the user permissions up the namespace tree. After using this script, the item is immediately accessible to the user. In addition, you can use this script to keep or delete the current set of policies for the item, including inherited ones. I haven't given the script the whole battery of tests yet, so if you play around with the code, try it on your test server only. If you find any problems or issues, let me know."

'=====================================================================

' File: AddItemSecurity.rss
' Summary: Demonstrates a script that can be used with RS.exe to
' set security on an item in Reporting Services.
'---------------------------------------------------------------------

' THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
' KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
' IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
' PARTICULAR PURPOSE.

'=====================================================================*/

'
' Variables that are passed on the command line with the -v switch:
' userName - the name of the user for which to add a policy
' roleName - the name of the role to apply for the user (i.e. Browser, Content Manager)
' itemPath - the path of the item for which you want to add the policy (i.e. /SampleReports)
' keepCurrentPolicy - whether to keep the current policy and add the new one
'
' Sample command line:
' rs -i AddItemSecurity.rss -s http://localhost/reportserver -v userName="MyTestUser"
' -v roleName="Browser" -v itemPath="/SampleReports" -v keepCurrentPolicy="True"


Public Sub Main()

Dim isRoot As Boolean = False
Dim inheritParent As Boolean
Dim policies() As Policy
Dim newPolicies() As Policy
Dim policy As New Policy()
Dim roles(0) As Role

roles(0) = New Role()

roles(0).Name = roleName

policy.Roles = roles

policy.GroupUserName = userName

While Not isRoot
' Once the root of the catalog is reached,
' stop applying policies

   If itemPath = "/" Then
      isRoot = True
   End If 

   policies = rs.GetPolicies(itemPath, inheritParent)

   ' If the user selects not to keep inherited or current policy,
   ' empty the policy

   If Not keepCurrentPolicy = "True" Then
      policies = Nothing
   End If 

   newPolicies = AddNewPolicy(policy, policies)

   rs.SetPolicies(itemPath, newPolicies)

   itemPath = GetParentPath(itemPath)

End While

Console.WriteLine("Policy successfully set.")

End Sub 'Main


' Method to parse the path of an item and retrieve
' the parent path of an item

Private Function GetParentPath(currentPath As String) As String

Dim delimiter As String = "/"
Dim rx As New System.Text.RegularExpressions.Regex(delimiter)
Dim childPath As String() = rx.Split(currentPath)
Dim parentLength As Integer = childPath.Length - 1
Dim parentPath(parentLength) As String
Dim i As Integer

For i = 0 To parentLength - 1
   parentPath(i) = childPath(i)
Next i

If parentPath.Length = 1 Then
   Return "/"
Else
   Return String.Join("/", parentPath)
End If

End Function 'GetParentPath


' Takes the policy to add and applies it to the current set
' of policies if applicable

Private Function AddNewPolicy(policyToAdd As Policy, policies() As Policy) As Policy()
If Not (policies Is Nothing) Then
   Dim policy As Policy
   For Each policy In policies
      If policy.GroupUserName = policyToAdd.GroupUserName Then
         Throw New Exception("The supplied User policy already exists for the item.")
      End If
   Next policy 

   Dim list As New System.Collections.ArrayList(policies)
   list.Add(policyToAdd)
   Return CType(list.ToArray(GetType(Policy)), Policy())
Else
   policies = New Policy(0) {}
   policies(0) = policyToAdd
   Return policies
End If

End Function 'AddNewPolicy

Friday, August 11, 2006 11:39:56 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |   | 

The following content is intellectual property of Brian Keller, the original posting can be found here.

"I presented some demos at this year's PASS (Professional Association of SQL Server) Community Summit on how to use the rskeymgmt utility in Reporting Services. This is a crucial tool and should be used after every Reporting Services installation. What is it good for? Well, it can do several things, least of which is to extract and store the symmetric keys used to encrypt data in the report server database or catalog. This tool captures the complete key set that is defined during setup, and stores it as a file that you can save to disk or to removable storage media. You will absolutely need this key at some point if the account that is used for the ReportServer Windows service changes in some way (if a password is changed for instance) or if you want to connect a new report server to an existing report server database instance. Without the ability to apply this key at a later date to a report server instance, you may be forced to delete all encrypted data in your catalog including data source and user information. The rskeymgmt utility can help with that as well, but this shouldn't be necessary as long as you back up the key. The key is an integral part of storing encrypted data. If, at some point, the encryption key for the report server instance is different from the key used to store encrypted content in the database (i.e. a new report server installation, but an existing catalog), you report server will not function properly. So, bottom line, store your encryption key on a floppy disk for safe keeping using rskeymgmt. You can read the specifics about the tool on MSDN here"

Friday, August 11, 2006 11:27:19 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |   | 
Friday, August 11, 2006 9:01:29 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |   | 

Identifying the User during runtime sometimes can be usefull for your report header or footer, can be used to filter data or for parameters, and so on but it bars users from subscribing to reports, because Reporting Services is not able to identify the user from the subscription.

Brian Cooper had published a workaround for the known issue coming around using User!UserID in Reporting Services, but the content is gone...I discovered that during a discussion at the MSDN forum about the problem with User!UserID in datadriven subscriptions.

Jan Pieter Posthuma remembered the code and had the correct hint to solve this problem - many thanks!


Declare that parameter with a default value of the output of the custom code function (Code.UserName()) and thru out the report you use this parameter as replacement for the User!UserID. When scheduling this report you bind this parameter with the output from your subscription query.

In case you haven't got the custom code from the weblog:

Public Function UserName()
Try
Return Report.User!UserID
Catch
Return "System"
End Try
End Function

Friday, August 11, 2006 1:51:41 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |  |   | 

I have discovered, that several links I have had in my archive and also in this blog are currently not working anymore, because:

  • content has moved or is no longer available
  • blog was moved to another blogging software without migrating the content

If you would like to have an example:
http://brianecooper.com/coop/archive/2005/03/15/270.aspx
Brian has changed the blogging software and has not moved all posts yet.
I really would have needed the workaround he provided in his post urgently, but I only had stored the link and not the content...

Though some of my links aren´t working and useful content is not available anymore.
Therefor I decided not just to link content in the future but also to copy the content - including a reference to the original author and original source of course! - to my blog to assure availability.

Friday, August 11, 2006 1:30:34 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   | 

Definition from the SQL Server 2005 Product Guide:

"Analysis Management Objects (AMO) allows client applications to access the range of administrative commands and capabilities that are available to Analysis Services by using an object library that can provide object-level validation capabilities. This is an alternative to manually generating both the DDL scripts for Analysis commands and the often-lengthy contents of the ASSL ObjectDefinition element. Applications that use AMO can either connect and work directly with objects on an Analysis Services instance, or they can create such objects without an existing connection and persist the metadata for later deployment. AMO also “wraps” Analysis Services Scripting Language (ASSL) commands and elements."

Microsoft SQL Server 2005 Management Objects Collection from the Feature Pack for Microsoft SQL Server 2005 - April 2006

Introducing AMO Concepts

Readme for AMOBrowser Sample

AMO Security Classes

Programming AMO Security Objects

Analysis Services Concepts and Objects

Permissions and Access Rights (SSAS)

Friday, August 11, 2006 12:49:21 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |  |  |  |   | 
 Wednesday, August 09, 2006

Today a customer of mine remarked, that using the URL Access to show a report in an application without using the report manager does not refresh in a proper way if you use rc:Toolbar=false to hide the toolbar and leads to a non-refreshed report showing "old" values while displaying the toolbar shows a refreshed report

It seems, that activating the toolbar opens up a new session every time the report is opened whereas hiding the toolbar upholds the session and for that purpose the content is not re-rendered. If you want to get rid of this behavior you can use rs:ClearSession=true to force re-rendering and remove all report instances associated with an authenticated user from session.

Therefor the correct URL Access Syntax to access a report in HTML mode without a toolbar and with actual data will be something like:
http://servername/reportserver?/folder/report name&rs:Command=Render&rs:format=HTML4.0&rc:Toolbar=false&rs:ClearSession=true

Wednesday, August 09, 2006 9:52:41 PM (Mitteleuropäische Zeit, UTC+01:00)  #     Author:Markus Fischer   Comments [0]   |   | 
Copyright © 2010 Markus Fischer. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.
Pick a theme: