<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments for Bob Lambert</title>
	<atom:link href="http://robertlambert.net/comments/feed/" rel="self" type="application/rss+xml" />
	<link>http://robertlambert.net</link>
	<description>on business-aligned information technology</description>
	<lastBuildDate>Tue, 17 Nov 2009 22:15:56 -0500</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.3</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>Comment on Data and Wine? by Chris Bradley</title>
		<link>http://robertlambert.net/2009/11/data-and-wine/comment-page-1/#comment-480</link>
		<dc:creator>Chris Bradley</dc:creator>
		<pubDate>Tue, 17 Nov 2009 22:15:56 +0000</pubDate>
		<guid isPermaLink="false">http://robertlambert.net/?p=677#comment-480</guid>
		<description>Reminds me of raindrops on roses and whiskers on kittens ;)</description>
		<content:encoded><![CDATA[<p>Reminds me of raindrops on roses and whiskers on kittens <img src='http://robertlambert.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Followership by Bob Lambert &#187; Blog Archive &#187; Followership II &#8211; Individualists, Enablers, &#38; Subversives</title>
		<link>http://robertlambert.net/2009/02/followership/comment-page-1/#comment-472</link>
		<dc:creator>Bob Lambert &#187; Blog Archive &#187; Followership II &#8211; Individualists, Enablers, &#38; Subversives</dc:creator>
		<pubDate>Sun, 01 Nov 2009 21:18:25 +0000</pubDate>
		<guid isPermaLink="false">http://robertlambert.net/?p=176#comment-472</guid>
		<description>[...] a previous post I posed this question: &#8220;more people are followers than leaders, so isn’t it more important [...]</description>
		<content:encoded><![CDATA[<p>[...] a previous post I posed this question: &#8220;more people are followers than leaders, so isn’t it more important [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on DQ, he isn&#8217;t so dumb he just needs glasses by IAIDQ Festival del IDQ Bloggers - Episode #2 &#124; The DOBlog</title>
		<link>http://robertlambert.net/2009/05/dq-he-isnt-so-dumb-he-just-needs-glasses/comment-page-1/#comment-120</link>
		<dc:creator>IAIDQ Festival del IDQ Bloggers - Episode #2 &#124; The DOBlog</dc:creator>
		<pubDate>Mon, 01 Jun 2009 19:16:56 +0000</pubDate>
		<guid isPermaLink="false">http://robertlambert.net/?p=418#comment-120</guid>
		<description>[...] this thought provoking post, Bob Lambert  shares his insights into why Project Sponsors aren&#8217;t blind, they just need glasses. In it, he highlights an all to common problem in poorly aligned IT projects and [...]</description>
		<content:encoded><![CDATA[<p>[...] this thought provoking post, Bob Lambert  shares his insights into why Project Sponsors aren&#8217;t blind, they just need glasses. In it, he highlights an all to common problem in poorly aligned IT projects and [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on SQL Server Row Level Security @ Richmond Code Camp 2009.1 by Bob</title>
		<link>http://robertlambert.net/2009/04/sql-server-row-level-security-richmond-code-camp-20091/comment-page-1/#comment-65</link>
		<dc:creator>Bob</dc:creator>
		<pubDate>Mon, 27 Apr 2009 13:49:40 +0000</pubDate>
		<guid isPermaLink="false">http://robertlambert.net/?p=411#comment-65</guid>
		<description>Here are the object creates and presentation scripts presented  in

Pretty Good Row Level Security

At Richmond Code Camp 2009.1 (&lt;a href=&quot;http://richmondcodecamp.org/&quot; rel=&quot;nofollow&quot;&gt;http://richmondcodecamp.org/&lt;/a&gt;) 
Bob Lambert and 
Nic Morel

CapTech Ventures, Inc.
blambert@captechventures.com, http://robertlambert.net 
nmorel@captechventures.com
See also Protecting Your Data with Row Level Security for SQL Server Databases at Dr Dobbs Portal, http://www.ddj.com/database/215900773 

Note: users other than dbo are granted only access to views, that is in example 2 mdavis should only have access to the view ordersummary, in the later examples bobama only to vssalestotals and vsemployee.

---------------------------------------------------------------------------
-- Sales user Access table
USE [AdventureWorks]
GO
/****** Object:  Table [Security].[SalesAccess]    Script Date: 04/27/2009 08:11:14 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [Security].[SalesAccess](
	[UserID] [varchar](20) NOT NULL,
	[TerritoryID] [int] NOT NULL
) ON [PRIMARY]

GO

---------------------------------------------------------------------------
-- HR User Access Table

SET ANSI_PADDING ON
USE [AdventureWorks]
GO
/****** Object:  Table [Security].[HRAccess]    Script Date: 04/27/2009 08:11:56 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [Security].[HRAccess](
	[UserID] [varchar](20) NOT NULL,
	[DepartmentID] [smallint] NOT NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING ON

---------------------------------------------------------------------------
-- select * from [Security].[SalesAccess]    


UserID               TerritoryID
-------------------- -----------
sordway              1
sordway              2
sordway              3
bobama               1
jmccain              2
jkerry               6
jkerry               7
jkerry               8
jkerry               9
mromney              7
mromney              8
dbo                  1
dbo                  2

---------------------------------------------------------------------------
-- select * from [Security].[HRAccess]   

UserID               DepartmentID
-------------------- ------------
bobama               4
bobama               5
bobama               6
dbo                  5
dbo                  6
dbo                  7
dbo                  8
dbo                  9
dbo                  10
dbo                  11
dbo                  12
dbo                  13
dbo                  14
dbo                  15
dbo                  16

(15 row(s) affected)



---------------------------------------------------------------------------
-- table valued function accessing sales data joining to the sales security access table


USE [AdventureWorks]
GO
/****** Object:  UserDefinedFunction [Security].[ufnGetSalesTotals]    Script Date: 04/25/2009 12:25:48 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [Security].[ufnGetSalesTotals] 
(	
	@UserId VARCHAR(20)
)
RETURNS TABLE 
AS
RETURN 
(
	SELECT 
		pvt.[SalesPersonID]
		,pvt.[FullName]
		,pvt.[Title]
		,pvt.[SalesTerritory]
		,pvt.[2002]
		,pvt.[2003]
		,pvt.[2004] 
	FROM (SELECT 
			soh.[SalesPersonID]
			,c.[FirstName] + &#039; &#039; + COALESCE(c.[MiddleName], &#039;&#039;) + &#039; &#039; + c.[LastName] AS [FullName]
			,e.[Title]
			,st.[Name] AS [SalesTerritory]
			,soh.[SubTotal]
			,YEAR(DATEADD(m, 6, soh.[OrderDate])) AS [FiscalYear] 
		FROM [Sales].[SalesPerson] sp 
			INNER JOIN [Sales].[SalesOrderHeader] soh 
			ON sp.[SalesPersonID] = soh.[SalesPersonID]
			INNER JOIN [Sales].[SalesTerritory] st 
			ON sp.[TerritoryID] = st.[TerritoryID]
			INNER JOIN Security.SalesAccess sa   /* this is the added join */
			ON sa.TerritoryID = st.[TerritoryID]
			AND sa.UserId = @UserID
			INNER JOIN [HumanResources].[Employee] e 
			ON soh.[SalesPersonID] = e.[EmployeeID] 
			INNER JOIN [Person].[Contact] c 
			ON e.[ContactID] = c.ContactID 
		) AS soh 
	PIVOT 
	(
		SUM([SubTotal]) 
		FOR [FiscalYear] 
		IN ([2002], [2003], [2004])
	) AS pvt
)

---------------------------------------------------------------------------
-- View passing userid to the function above


USE [AdventureWorks]
GO
/****** Object:  View [Security].[vsSalesTotals]    Script Date: 04/25/2009 12:26:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE VIEW [Security].[vsSalesTotals] 
AS 
SELECT 
		 [SalesPersonID]
		,[FullName]
		,[Title]
		,[SalesTerritory]
		,[2002]
		,[2003]
		,[2004] 

FROM Security.ufnGetSalesTotals(USER)

---------------------------------------------------------------------------
-- table valued function accessing employee data joining to the HR security access table


USE [AdventureWorks]
GO
/****** Object:  UserDefinedFunction [Security].[ufnGetEmployeeData]    Script Date: 04/25/2009 12:26:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [Security].[ufnGetEmployeeData] 
(	
	@UserId VARCHAR(20)
)
RETURNS TABLE 
AS
RETURN 
(
	SELECT 
		e.[EmployeeID]
		,c.[Title]
		,c.[FirstName]
		,c.[MiddleName]
		,c.[LastName]
		,c.[Suffix]
		,e.[Title] AS [JobTitle] 
		,edh.DepartmentID
		,dpt.Name AS [DepartmentName]
		,shr.UserID
		,c.[Phone]
		,c.[EmailAddress]
		,c.[EmailPromotion]
		,a.[AddressLine1]
		,a.[AddressLine2]
		,a.[City]
		,sp.[Name] AS [StateProvinceName] 
		,a.[PostalCode]
		,cr.[Name] AS [CountryRegionName] 
		,c.[AdditionalContactInfo]
	FROM [HumanResources].[Employee] e
		INNER JOIN [Person].[Contact] c 
		ON c.[ContactID] = e.[ContactID]
		INNER JOIN [HumanResources].[EmployeeAddress] ea 
		ON e.[EmployeeID] = ea.[EmployeeID] 
		INNER JOIN [Person].[Address] a 
		ON ea.[AddressID] = a.[AddressID]
		INNER JOIN [Person].[StateProvince] sp 
		ON sp.[StateProvinceID] = a.[StateProvinceID]
		INNER JOIN [Person].[CountryRegion] cr 
		ON cr.[CountryRegionCode] = sp.[CountryRegionCode]
		INNER JOIN HumanResources.EmployeeDepartmentHistory edh
		ON edh.EmployeeID = e.EmployeeID
		AND	edh.EndDate is null
		INNER JOIN Security.HRAccess shr /* this is the added join */
		ON shr.DepartmentID = edh.DepartmentID
		and shr.UserID = @UserID
		INNER JOIN HumanResources.Department dpt
		ON dpt.DepartmentID = edh.DepartmentID
)
---------------------------------------------------------------------------
-- View passing userid to the function above

USE [AdventureWorks]
GO
/****** Object:  View [Security].[vsEmployee]    Script Date: 04/25/2009 12:27:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE VIEW [Security].[vsEmployee] 
AS 
SELECT 
 		[EmployeeID]
		,[Title]
		,[FirstName]
		,[MiddleName]
		,[LastName]
		,[Suffix]
		,[JobTitle] 
		,DepartmentID
		,[DepartmentName]
		,UserID
		,[Phone]
		,[EmailAddress]
		,[EmailPromotion]
		,[AddressLine1]
		,[AddressLine2]
		,[City]
		,[StateProvinceName] 
		,[PostalCode]
		,[CountryRegionName] 
		,[AdditionalContactInfo]
FROM Security.ufnGetEmployeeData(USER)
    
GO
EXEC sys.sp_addextendedproperty @name=N&#039;MS_Description&#039;, @value=N&#039;Employee names and addresses.&#039; , @level0type=N&#039;SCHEMA&#039;,@level0name=N&#039;Security&#039;, @level1type=N&#039;VIEW&#039;,@level1name=N&#039;vsEmployee&#039;

---------------------------------------------------------------------------
-- Presentation scripts

------------------------------------
-- Dr Dobbs Example 1: dbo
------------------------------------

-- Connect blambert

use rls

--The database includes these orders

select * from orders
where department in (&#039;East&#039;, &#039;Southeast&#039;, &#039;Northeast&#039;)

--Here are the contents of the user access table
select * from useraccess;

--and here are the results of a query summing orders accessible by 
-- a particular user
select * from getordersummary (&#039;blambert&#039;)

-- here&#039;s the view encapsulating the getordersummary function

select * from ordersummary

select user

------------------------------------
-- Dr Dobbs Example 2: mdavis
------------------------------------

-- Connect mdavis
select user

use rls

--review the orders table

select * from orders
where department in (&#039;East&#039;, &#039;Southeast&#039;, &#039;Northeast&#039;)

--review the user access table
select * from useraccess;

--review the getordersummary table-valued function
select * from getordersummary (&#039;mdavis&#039;)

-- review the ordersummary view

select * from ordersummary

------------------------------------
-- AdventureWorks Example 1: dbo
------------------------------------

-- Connect blambert

use AdventureWorks

--Adventureworks includes this view, providing a pivoted sales report

select * from Sales.vSalesPersonSalesByFiscalYears 

--Here are the contents of the user access table

select * from Security.SalesAccess

--Here are territory codes

select * from Sales.SalesTerritory

--and here are the results of a query summing orders accessible by 
-- a particular user
select * from Security.ufnGetSalesTotals(&#039;jmccain&#039;)

-- here&#039;s the view encapsulating the getordersummary function

select * from Security.vsSalesTotals

select user

------------------------------------
-- AdventureWorks Example 1: bobama
------------------------------------

-- Connect bobama

use AdventureWorks

--Adventureworks includes this view, providing a pivoted sales report

select * from Sales.vSalesPersonSalesByFiscalYears 

--Here are the contents of the user access table

select * from Security.SalesAccess

--Here are territory codes

select * from Sales.SalesTerritory

--and here are the results of a query summing orders accessible by 
-- a particular user
select * from Security.ufnGetSalesTotals(&#039;bobama&#039;)

-- here&#039;s the view encapsulating the getordersummary function

select * from Security.vsSalesTotals

select user

------------------------------------
-- AdventureWorks Example 2: dbo
------------------------------------

-- Connect blambert

use AdventureWorks

--Adventureworks includes this view, providing employee data

select * from HumanResources.vEmployee 

--Here are the contents of the user access table

select * from Security.HRAccess

--Here are department ids

select * from HumanResources.Department
select * from HumanResources.EmployeeDepartmentHistory where enddate is null

--and here are the results of a query summing using the table valued function to list employees

select * from Security.ufnGetEmployeeData(&#039;jmccain&#039;)

-- here&#039;s the view encapsulating the ufnGetEmployeeData function

select * from Security.vsEmployee

select user
------------------------------------
-- AdventureWorks Example 2: bobama
------------------------------------

-- Connect bobama

use AdventureWorks

--Adventureworks includes this view, providing employee data

select * from HumanResources.vEmployee 

--Here are the contents of the user access table

select * from Security.HRAccess

--Here are department ids

select * from HumanResources.Department
select * from HumanResources.EmployeeDepartmentHistory where enddate is null

--and here are the results of a query summing using the table valued function to list employees

select * from Security.ufnGetEmployeeData(&#039;jmccain&#039;)

-- here&#039;s the view encapsulating the ufnGetEmployeeData function

select * from Security.vsEmployee

select user</description>
		<content:encoded><![CDATA[<p>Here are the object creates and presentation scripts presented  in</p>
<p>Pretty Good Row Level Security</p>
<p>At Richmond Code Camp 2009.1 (<a href="http://richmondcodecamp.org/" rel="nofollow">http://richmondcodecamp.org/</a>)<br />
Bob Lambert and<br />
Nic Morel</p>
<p>CapTech Ventures, Inc.<br />
<a href="mailto:blambert@captechventures.com">blambert@captechventures.com</a>, <a href="http://robertlambert.net" rel="nofollow">http://robertlambert.net</a><br />
<a href="mailto:nmorel@captechventures.com">nmorel@captechventures.com</a><br />
See also Protecting Your Data with Row Level Security for SQL Server Databases at Dr Dobbs Portal, <a href="http://www.ddj.com/database/215900773" rel="nofollow">http://www.ddj.com/database/215900773</a> </p>
<p>Note: users other than dbo are granted only access to views, that is in example 2 mdavis should only have access to the view ordersummary, in the later examples bobama only to vssalestotals and vsemployee.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; Sales user Access table<br />
USE [AdventureWorks]<br />
GO<br />
/****** Object:  Table [Security].[SalesAccess]    Script Date: 04/27/2009 08:11:14 ******/<br />
SET ANSI_NULLS ON<br />
GO<br />
SET QUOTED_IDENTIFIER ON<br />
GO<br />
SET ANSI_PADDING ON<br />
GO<br />
CREATE TABLE [Security].[SalesAccess](<br />
	[UserID] [varchar](20) NOT NULL,<br />
	[TerritoryID] [int] NOT NULL<br />
) ON [PRIMARY]</p>
<p>GO</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; HR User Access Table</p>
<p>SET ANSI_PADDING ON<br />
USE [AdventureWorks]<br />
GO<br />
/****** Object:  Table [Security].[HRAccess]    Script Date: 04/27/2009 08:11:56 ******/<br />
SET ANSI_NULLS ON<br />
GO<br />
SET QUOTED_IDENTIFIER ON<br />
GO<br />
SET ANSI_PADDING ON<br />
GO<br />
CREATE TABLE [Security].[HRAccess](<br />
	[UserID] [varchar](20) NOT NULL,<br />
	[DepartmentID] [smallint] NOT NULL<br />
) ON [PRIMARY]<br />
GO<br />
SET ANSI_PADDING ON</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; select * from [Security].[SalesAccess]    </p>
<p>UserID               TerritoryID<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8211;<br />
sordway              1<br />
sordway              2<br />
sordway              3<br />
bobama               1<br />
jmccain              2<br />
jkerry               6<br />
jkerry               7<br />
jkerry               8<br />
jkerry               9<br />
mromney              7<br />
mromney              8<br />
dbo                  1<br />
dbo                  2</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; select * from [Security].[HRAccess]   </p>
<p>UserID               DepartmentID<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;<br />
bobama               4<br />
bobama               5<br />
bobama               6<br />
dbo                  5<br />
dbo                  6<br />
dbo                  7<br />
dbo                  8<br />
dbo                  9<br />
dbo                  10<br />
dbo                  11<br />
dbo                  12<br />
dbo                  13<br />
dbo                  14<br />
dbo                  15<br />
dbo                  16</p>
<p>(15 row(s) affected)</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; table valued function accessing sales data joining to the sales security access table</p>
<p>USE [AdventureWorks]<br />
GO<br />
/****** Object:  UserDefinedFunction [Security].[ufnGetSalesTotals]    Script Date: 04/25/2009 12:25:48 ******/<br />
SET ANSI_NULLS ON<br />
GO<br />
SET QUOTED_IDENTIFIER ON<br />
GO</p>
<p>CREATE FUNCTION [Security].[ufnGetSalesTotals]<br />
(<br />
	@UserId VARCHAR(20)<br />
)<br />
RETURNS TABLE<br />
AS<br />
RETURN<br />
(<br />
	SELECT<br />
		pvt.[SalesPersonID]<br />
		,pvt.[FullName]<br />
		,pvt.[Title]<br />
		,pvt.[SalesTerritory]<br />
		,pvt.[2002]<br />
		,pvt.[2003]<br />
		,pvt.[2004]<br />
	FROM (SELECT<br />
			soh.[SalesPersonID]<br />
			,c.[FirstName] + &#8216; &#8216; + COALESCE(c.[MiddleName], &#8221;) + &#8216; &#8216; + c.[LastName] AS [FullName]<br />
			,e.[Title]<br />
			,st.[Name] AS [SalesTerritory]<br />
			,soh.[SubTotal]<br />
			,YEAR(DATEADD(m, 6, soh.[OrderDate])) AS [FiscalYear]<br />
		FROM [Sales].[SalesPerson] sp<br />
			INNER JOIN [Sales].[SalesOrderHeader] soh<br />
			ON sp.[SalesPersonID] = soh.[SalesPersonID]<br />
			INNER JOIN [Sales].[SalesTerritory] st<br />
			ON sp.[TerritoryID] = st.[TerritoryID]<br />
			INNER JOIN Security.SalesAccess sa   /* this is the added join */<br />
			ON sa.TerritoryID = st.[TerritoryID]<br />
			AND sa.UserId = @UserID<br />
			INNER JOIN [HumanResources].[Employee] e<br />
			ON soh.[SalesPersonID] = e.[EmployeeID]<br />
			INNER JOIN [Person].[Contact] c<br />
			ON e.[ContactID] = c.ContactID<br />
		) AS soh<br />
	PIVOT<br />
	(<br />
		SUM([SubTotal])<br />
		FOR [FiscalYear]<br />
		IN ([2002], [2003], [2004])<br />
	) AS pvt<br />
)</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; View passing userid to the function above</p>
<p>USE [AdventureWorks]<br />
GO<br />
/****** Object:  View [Security].[vsSalesTotals]    Script Date: 04/25/2009 12:26:17 ******/<br />
SET ANSI_NULLS ON<br />
GO<br />
SET QUOTED_IDENTIFIER ON<br />
GO</p>
<p>CREATE VIEW [Security].[vsSalesTotals]<br />
AS<br />
SELECT<br />
		 [SalesPersonID]<br />
		,[FullName]<br />
		,[Title]<br />
		,[SalesTerritory]<br />
		,[2002]<br />
		,[2003]<br />
		,[2004] </p>
<p>FROM Security.ufnGetSalesTotals(USER)</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; table valued function accessing employee data joining to the HR security access table</p>
<p>USE [AdventureWorks]<br />
GO<br />
/****** Object:  UserDefinedFunction [Security].[ufnGetEmployeeData]    Script Date: 04/25/2009 12:26:37 ******/<br />
SET ANSI_NULLS ON<br />
GO<br />
SET QUOTED_IDENTIFIER ON<br />
GO</p>
<p>CREATE FUNCTION [Security].[ufnGetEmployeeData]<br />
(<br />
	@UserId VARCHAR(20)<br />
)<br />
RETURNS TABLE<br />
AS<br />
RETURN<br />
(<br />
	SELECT<br />
		e.[EmployeeID]<br />
		,c.[Title]<br />
		,c.[FirstName]<br />
		,c.[MiddleName]<br />
		,c.[LastName]<br />
		,c.[Suffix]<br />
		,e.[Title] AS [JobTitle]<br />
		,edh.DepartmentID<br />
		,dpt.Name AS [DepartmentName]<br />
		,shr.UserID<br />
		,c.[Phone]<br />
		,c.[EmailAddress]<br />
		,c.[EmailPromotion]<br />
		,a.[AddressLine1]<br />
		,a.[AddressLine2]<br />
		,a.[City]<br />
		,sp.[Name] AS [StateProvinceName]<br />
		,a.[PostalCode]<br />
		,cr.[Name] AS [CountryRegionName]<br />
		,c.[AdditionalContactInfo]<br />
	FROM [HumanResources].[Employee] e<br />
		INNER JOIN [Person].[Contact] c<br />
		ON c.[ContactID] = e.[ContactID]<br />
		INNER JOIN [HumanResources].[EmployeeAddress] ea<br />
		ON e.[EmployeeID] = ea.[EmployeeID]<br />
		INNER JOIN [Person].[Address] a<br />
		ON ea.[AddressID] = a.[AddressID]<br />
		INNER JOIN [Person].[StateProvince] sp<br />
		ON sp.[StateProvinceID] = a.[StateProvinceID]<br />
		INNER JOIN [Person].[CountryRegion] cr<br />
		ON cr.[CountryRegionCode] = sp.[CountryRegionCode]<br />
		INNER JOIN HumanResources.EmployeeDepartmentHistory edh<br />
		ON edh.EmployeeID = e.EmployeeID<br />
		AND	edh.EndDate is null<br />
		INNER JOIN Security.HRAccess shr /* this is the added join */<br />
		ON shr.DepartmentID = edh.DepartmentID<br />
		and shr.UserID = @UserID<br />
		INNER JOIN HumanResources.Department dpt<br />
		ON dpt.DepartmentID = edh.DepartmentID<br />
)<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; View passing userid to the function above</p>
<p>USE [AdventureWorks]<br />
GO<br />
/****** Object:  View [Security].[vsEmployee]    Script Date: 04/25/2009 12:27:01 ******/<br />
SET ANSI_NULLS ON<br />
GO<br />
SET QUOTED_IDENTIFIER ON<br />
GO</p>
<p>CREATE VIEW [Security].[vsEmployee]<br />
AS<br />
SELECT<br />
 		[EmployeeID]<br />
		,[Title]<br />
		,[FirstName]<br />
		,[MiddleName]<br />
		,[LastName]<br />
		,[Suffix]<br />
		,[JobTitle]<br />
		,DepartmentID<br />
		,[DepartmentName]<br />
		,UserID<br />
		,[Phone]<br />
		,[EmailAddress]<br />
		,[EmailPromotion]<br />
		,[AddressLine1]<br />
		,[AddressLine2]<br />
		,[City]<br />
		,[StateProvinceName]<br />
		,[PostalCode]<br />
		,[CountryRegionName]<br />
		,[AdditionalContactInfo]<br />
FROM Security.ufnGetEmployeeData(USER)</p>
<p>GO<br />
EXEC sys.sp_addextendedproperty @name=N&#8217;MS_Description&#8217;, @value=N&#8217;Employee names and addresses.&#8217; , @level0type=N&#8217;SCHEMA&#8217;,@level0name=N&#8217;Security&#8217;, @level1type=N&#8217;VIEW&#8217;,@level1name=N&#8217;vsEmployee&#8217;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; Presentation scripts</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; Dr Dobbs Example 1: dbo<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>&#8211; Connect blambert</p>
<p>use rls</p>
<p>&#8211;The database includes these orders</p>
<p>select * from orders<br />
where department in (&#8217;East&#8217;, &#8216;Southeast&#8217;, &#8216;Northeast&#8217;)</p>
<p>&#8211;Here are the contents of the user access table<br />
select * from useraccess;</p>
<p>&#8211;and here are the results of a query summing orders accessible by<br />
&#8211; a particular user<br />
select * from getordersummary (&#8217;blambert&#8217;)</p>
<p>&#8211; here&#8217;s the view encapsulating the getordersummary function</p>
<p>select * from ordersummary</p>
<p>select user</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; Dr Dobbs Example 2: mdavis<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>&#8211; Connect mdavis<br />
select user</p>
<p>use rls</p>
<p>&#8211;review the orders table</p>
<p>select * from orders<br />
where department in (&#8217;East&#8217;, &#8216;Southeast&#8217;, &#8216;Northeast&#8217;)</p>
<p>&#8211;review the user access table<br />
select * from useraccess;</p>
<p>&#8211;review the getordersummary table-valued function<br />
select * from getordersummary (&#8217;mdavis&#8217;)</p>
<p>&#8211; review the ordersummary view</p>
<p>select * from ordersummary</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; AdventureWorks Example 1: dbo<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>&#8211; Connect blambert</p>
<p>use AdventureWorks</p>
<p>&#8211;Adventureworks includes this view, providing a pivoted sales report</p>
<p>select * from Sales.vSalesPersonSalesByFiscalYears </p>
<p>&#8211;Here are the contents of the user access table</p>
<p>select * from Security.SalesAccess</p>
<p>&#8211;Here are territory codes</p>
<p>select * from Sales.SalesTerritory</p>
<p>&#8211;and here are the results of a query summing orders accessible by<br />
&#8211; a particular user<br />
select * from Security.ufnGetSalesTotals(&#8217;jmccain&#8217;)</p>
<p>&#8211; here&#8217;s the view encapsulating the getordersummary function</p>
<p>select * from Security.vsSalesTotals</p>
<p>select user</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; AdventureWorks Example 1: bobama<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>&#8211; Connect bobama</p>
<p>use AdventureWorks</p>
<p>&#8211;Adventureworks includes this view, providing a pivoted sales report</p>
<p>select * from Sales.vSalesPersonSalesByFiscalYears </p>
<p>&#8211;Here are the contents of the user access table</p>
<p>select * from Security.SalesAccess</p>
<p>&#8211;Here are territory codes</p>
<p>select * from Sales.SalesTerritory</p>
<p>&#8211;and here are the results of a query summing orders accessible by<br />
&#8211; a particular user<br />
select * from Security.ufnGetSalesTotals(&#8217;bobama&#8217;)</p>
<p>&#8211; here&#8217;s the view encapsulating the getordersummary function</p>
<p>select * from Security.vsSalesTotals</p>
<p>select user</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; AdventureWorks Example 2: dbo<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>&#8211; Connect blambert</p>
<p>use AdventureWorks</p>
<p>&#8211;Adventureworks includes this view, providing employee data</p>
<p>select * from HumanResources.vEmployee </p>
<p>&#8211;Here are the contents of the user access table</p>
<p>select * from Security.HRAccess</p>
<p>&#8211;Here are department ids</p>
<p>select * from HumanResources.Department<br />
select * from HumanResources.EmployeeDepartmentHistory where enddate is null</p>
<p>&#8211;and here are the results of a query summing using the table valued function to list employees</p>
<p>select * from Security.ufnGetEmployeeData(&#8217;jmccain&#8217;)</p>
<p>&#8211; here&#8217;s the view encapsulating the ufnGetEmployeeData function</p>
<p>select * from Security.vsEmployee</p>
<p>select user<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8211; AdventureWorks Example 2: bobama<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>&#8211; Connect bobama</p>
<p>use AdventureWorks</p>
<p>&#8211;Adventureworks includes this view, providing employee data</p>
<p>select * from HumanResources.vEmployee </p>
<p>&#8211;Here are the contents of the user access table</p>
<p>select * from Security.HRAccess</p>
<p>&#8211;Here are department ids</p>
<p>select * from HumanResources.Department<br />
select * from HumanResources.EmployeeDepartmentHistory where enddate is null</p>
<p>&#8211;and here are the results of a query summing using the table valued function to list employees</p>
<p>select * from Security.ufnGetEmployeeData(&#8217;jmccain&#8217;)</p>
<p>&#8211; here&#8217;s the view encapsulating the ufnGetEmployeeData function</p>
<p>select * from Security.vsEmployee</p>
<p>select user</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on IT should own the misalignment problem by Bob</title>
		<link>http://robertlambert.net/2009/04/it-should-own-the-misalignment-problem/comment-page-1/#comment-61</link>
		<dc:creator>Bob</dc:creator>
		<pubDate>Fri, 24 Apr 2009 16:34:52 +0000</pubDate>
		<guid isPermaLink="false">http://robertlambert.net/?p=401#comment-61</guid>
		<description>Ara and Jonathon thanks for your insightful comments, both here and at your blogs, on this topic - great stuff and I&#039;m learning from the exchange.  Ara, in answer to your comment I also wouldn&#039;t discount relationship building as a critical element of aligning with the business, but I&#039;ve observed a tendency of some to focus on relationship building without improving the quality of the work.  In spite of my parenthetical comment, I agree you can&#039;t have one without the other, as you correctly pointed out.  
It is worth pointing out here that there&#039;s a risk in working on the relationship without visibly improving performance.  The risk is that is may be seen as image building, and, to Jonathon&#039;s point, may reduce IT&#039;s competitiveness in the face of potential outsourcing.</description>
		<content:encoded><![CDATA[<p>Ara and Jonathon thanks for your insightful comments, both here and at your blogs, on this topic &#8211; great stuff and I&#8217;m learning from the exchange.  Ara, in answer to your comment I also wouldn&#8217;t discount relationship building as a critical element of aligning with the business, but I&#8217;ve observed a tendency of some to focus on relationship building without improving the quality of the work.  In spite of my parenthetical comment, I agree you can&#8217;t have one without the other, as you correctly pointed out.<br />
It is worth pointing out here that there&#8217;s a risk in working on the relationship without visibly improving performance.  The risk is that is may be seen as image building, and, to Jonathon&#8217;s point, may reduce IT&#8217;s competitiveness in the face of potential outsourcing.</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on IT should own the misalignment problem by IT&#8217;s Interest in Business/IT Alignment : Practical Analyst</title>
		<link>http://robertlambert.net/2009/04/it-should-own-the-misalignment-problem/comment-page-1/#comment-60</link>
		<dc:creator>IT&#8217;s Interest in Business/IT Alignment : Practical Analyst</dc:creator>
		<pubDate>Fri, 24 Apr 2009 04:23:54 +0000</pubDate>
		<guid isPermaLink="false">http://robertlambert.net/?p=401#comment-60</guid>
		<description>[...] Lambert says IT should take the initiative in solving problems  of business/IT misalignment, and thinks the requirements process can be an [...]</description>
		<content:encoded><![CDATA[<p>[...] Lambert says IT should take the initiative in solving problems  of business/IT misalignment, and thinks the requirements process can be an [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on IT should own the misalignment problem by Jonathan Babcock</title>
		<link>http://robertlambert.net/2009/04/it-should-own-the-misalignment-problem/comment-page-1/#comment-56</link>
		<dc:creator>Jonathan Babcock</dc:creator>
		<pubDate>Tue, 21 Apr 2009 00:41:35 +0000</pubDate>
		<guid isPermaLink="false">http://robertlambert.net/?p=401#comment-56</guid>
		<description>Interesting articles, Bob and Ara. 

A thought that crossed my mind as I read your articles is that IT has an interest in taking the initiative in making Business/IT alignment work because corporate IT is seen increasingly as just another vendor. These days, the business has other well-marketed options such as outsourcing and off-the-shelf. If they can&#039;t get things done in-house, they know they have other options.

IT needs to provide a compelling value proposition and &quot;sell&quot; its services to the business customer almost as if it were competing for it&#039;s business on the open market. As IT folk, we&#039;re certainly incented to reach out and keep the customer relationship healthy and that biz/it alignment in balance.</description>
		<content:encoded><![CDATA[<p>Interesting articles, Bob and Ara. </p>
<p>A thought that crossed my mind as I read your articles is that IT has an interest in taking the initiative in making Business/IT alignment work because corporate IT is seen increasingly as just another vendor. These days, the business has other well-marketed options such as outsourcing and off-the-shelf. If they can&#8217;t get things done in-house, they know they have other options.</p>
<p>IT needs to provide a compelling value proposition and &#8220;sell&#8221; its services to the business customer almost as if it were competing for it&#8217;s business on the open market. As IT folk, we&#8217;re certainly incented to reach out and keep the customer relationship healthy and that biz/it alignment in balance.</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on IT should own the misalignment problem by Ara Trembly</title>
		<link>http://robertlambert.net/2009/04/it-should-own-the-misalignment-problem/comment-page-1/#comment-55</link>
		<dc:creator>Ara Trembly</dc:creator>
		<pubDate>Fri, 17 Apr 2009 15:19:42 +0000</pubDate>
		<guid isPermaLink="false">http://robertlambert.net/?p=401#comment-55</guid>
		<description>Well said.  I like the idea of IT taking up the reins and going for it when it comes to establishing better relationships, and certainly IT has substance to bring.  But can we really &quot;take emotions out of the picture&quot;?  Probably not, unless we subscribe to the Vulcan code of emotive flatness.  The key is to leverage the parties&#039; emotions (on both sides) by championing personal responsibility and looking beyond our own selfish needs, jealousies or fears.  If we start by magnifying, then changing the emotional climate, the results for business and IT will improve immeasurably.</description>
		<content:encoded><![CDATA[<p>Well said.  I like the idea of IT taking up the reins and going for it when it comes to establishing better relationships, and certainly IT has substance to bring.  But can we really &#8220;take emotions out of the picture&#8221;?  Probably not, unless we subscribe to the Vulcan code of emotive flatness.  The key is to leverage the parties&#8217; emotions (on both sides) by championing personal responsibility and looking beyond our own selfish needs, jealousies or fears.  If we start by magnifying, then changing the emotional climate, the results for business and IT will improve immeasurably.</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on IT PMs need IT experience by Tania</title>
		<link>http://robertlambert.net/2009/01/it-pms-need-it-experience/comment-page-1/#comment-54</link>
		<dc:creator>Tania</dc:creator>
		<pubDate>Sat, 11 Apr 2009 23:35:56 +0000</pubDate>
		<guid isPermaLink="false">http://robertlambert.net/?p=19#comment-54</guid>
		<description>Hi,
Thanks for article. Everytime like to read you.

Have a nice day
Tania</description>
		<content:encoded><![CDATA[<p>Hi,<br />
Thanks for article. Everytime like to read you.</p>
<p>Have a nice day<br />
Tania</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on No business value in nulls by Bob</title>
		<link>http://robertlambert.net/2009/04/no-business-value-in-nulls/comment-page-1/#comment-51</link>
		<dc:creator>Bob</dc:creator>
		<pubDate>Wed, 08 Apr 2009 18:07:46 +0000</pubDate>
		<guid isPermaLink="false">http://robertlambert.net/?p=345#comment-51</guid>
		<description>Andy, great examples, and I definitely agree with your approach.  Still, it seems to me they are about how to represent the business requirement in a design.  Nulls are a valid tool for the DB/code-literate in design, but in terms of business requirements I still think probably never.  I think of all business requirements working on normalized data, thereby giving the designer/developer full control of design decisions and not cutting off any data design options.  Given that, to me the player_average table is a (probably appropriate) denormalization of the player_at_bat_event table, of which there would be no row for the player who has not yet faced a pitcher.  So I think we&#039;re coming from the same place, just in different stages of the development life cycle.  I suppose a clarifying comment is in order: &quot;no business value in nulls until design.&quot;</description>
		<content:encoded><![CDATA[<p>Andy, great examples, and I definitely agree with your approach.  Still, it seems to me they are about how to represent the business requirement in a design.  Nulls are a valid tool for the DB/code-literate in design, but in terms of business requirements I still think probably never.  I think of all business requirements working on normalized data, thereby giving the designer/developer full control of design decisions and not cutting off any data design options.  Given that, to me the player_average table is a (probably appropriate) denormalization of the player_at_bat_event table, of which there would be no row for the player who has not yet faced a pitcher.  So I think we&#8217;re coming from the same place, just in different stages of the development life cycle.  I suppose a clarifying comment is in order: &#8220;no business value in nulls until design.&#8221;</p>
]]></content:encoded>
	</item>
</channel>
</rss>
