I have several databases that each have a table called, say, products
.
One of these databases (the "master") contains products that should be visible from all databases.
I do this by having an allproducts
view as follows:
CREATE VIEW allproducts AS
SELECT col[...] FROM products
UNION ALL SELECT col[...] FROM master.dbo.products;
This works well, except that the master database's allproducts
view needs a definition that doesn't bring in its own products:
CREATE VIEW allproducts AS
SELECT col[...] FROM products;
To simplify things a little, I'd like to have a common view definition, something like the following:
CREATE VIEW allproducts AS
SELECT col[...] FROM products
UNION ALL SELECT col[...] FROM master.dbo.products
WHERE (DB_NAME() <> 'master');
This works, but I'm concerned about performance. So, is the DB_NAME()
function deterministic, and if so, will SQL Server shortcut the entire right side of the UNION ALL
based on the comparison?
If DB_NAME()
is evaluated for each row of master.dbo.products
, is there a cleaner way to do this, or must I maintain separate view definitions?
UPDATE: "All metadata functions are nondeterministic. This means these functions do not always return the same results every time they are called, even with the same set of input values." - http://msdn.microsoft.com/en-us/library/ms187812.aspx
I found another question where someone had a similar situation and found a reasonable workaround:
So the main part of the question has been answered. Even though DB_NAME() is nondeterministic, the execution plans are the same for calling a deterministic UDF versus calling DB_NAME(), and performance indicates that the DB_NAME() result does short-cut the other branches of the query. Neither are quite as fast as a scalar comparison like "0=1" in the WHERE clause, so even deterministic functions don't fully optimize the plan. I can live with a UDF, so I'm going to go that direction for this situation.