Common TVF in SQL Server to get results from different schema - sql-server

I have been using SQL Server for the past month and I need a suggestion from SQL Server folks to help me on this use case.
The tables below are just to explain about the idea that I am looking for.
I have tables in different schema like this:
MyDb.dbo.Festivals
MyDb.India.Festivals
MyDb.China.Festivals
MyDb.USA.Festivals
I am writing a table value function without any schema prefixed in it like
CREATE FUNCTION getFestivals()
RETURNS TABLE
AS
RETURN
(SELECT * FROM festivals)
As I haven't applied any schema, it defaults to dbo and creates the TVF as dbo.getFestivals(). Now I have created synonyms for all other schemas
CREATE SYNONYM India.getFestivals FOR dbo.getFestivals;
CREATE SYNONYM USA.getFestivals FOR dbo.getFestivals;
I tried to query like
SELECT *
FROM MyDb.India.getFestivals()
and it returns the festivals from dbo.festivals and not india.festivals.
I understand that though the synonyms, we've created it just executes the select query in the dbo schema context and not in india schema context.
I want suggestions on how to have a common table value function that will query based on the schema prefixed, i.e. MyDB.India.getFestivals() should get festivals from India and MyDB.USA.getFestivals() should return festivals from USA.
Question
Is there a way I can have a table value function that can query based on the schema context.
the only possible way I can think of is to create the same TableValue function in all schemas
Caveats
I have to stick to table value function only and the above use case is a sample scenario to explain my problem

I understand that though the synonyms, we've created it just executes
the select query in the dbo schema context and not in india schema
context.
You should always schema qualify objects in your queries, since you did not do it, SQL Server first looks for festivals in the same schema where the procedure resides, if it's not found then dbo schema is checked, if it's not found even in dbo, the error is raised.
In your case procedure resides in dbo schema so only dbo schema is checked in order to find festivals.
It may be wrong design if many "similar" tables are created instead of one table, can you merge them all into one table adding country_id to distinguish the country?
If not, can you at least add this field to every table? If it's so, just add the field for the country in every table, add check constraint on this field to reflect the only country that is stored in every table an then use partitioned view in your function.
Partitioned view is a view composed of union all of some tables with the same structure, each of which has check constraint on the same column that defines the values this column is restricted to. When you use this view with the filter on country column, all the tables except for the correct one will be eliminated from execution plan thanks to check constraint defined on this column.
So you can change your function to accept the only parameter that is country and it will read only one table corresponding to parameter passed.
More on partitioned views here: Using Partitioned Views

Related

Create a default column filter at schema/database level in Oracle and SQL Server?

We have enabled versioning of database records in order to maintain multiple versions of product configurations for our customers. To achieve this, we have created 'Version' column in all our tables with default entry 'core_version'. Customers can create a new copy of the same records by changing one or two column values and say that as 'customer_version1'. So, the PK of all our tables are (ID column and Version).
Something like this:
Now, the version column will act as an identifier, when performing CRUD operations via application as well as when executing sql queries directly in DB, to ensure against which version of records the CRUD operation update should happen.
Is there any way to achieve this in Oracle & SQL server? A Default filter for the "Version" column at Schema level that should get added as a mandatory where clause on performing/executing any query operation.
Say, If want only "Core_version" records. Then, Select * from employee; should return me only 3 records respective to core_version without having the version column filter explicitly in query.

SQL Server + triggers: How to get information about the inserted/deleted tables

Is there any way to get information about the updated/deleted tables in a trigger, meaning
which columns are in the inserted/deleted tables?
which data types do they have?
The background for this question is: I would like to create a 'generic' trigger which can be used without having need to be adapted for the table in question.
Dummy code:
foreach column in inserted table
get column name and data type and column (e.g. to exclude text columns or columns with a special name)
if the value has changed do some logging into another table
Unfortunately I could not find the needed information so far; I have to admit that I don't know the proper key words which have to be used.
It would even be helpful to get a list of functions (e.g. UPDATE()) which can be used in triggers to query information about the inserted/deleted tables.
The TSQL code should work on MS SQL Server >= 2008.
TIA

Database "Identity" field and auto-increment

I'm writing my first database application and I've got an ambiguity I can't seem to find an answer for. I have an id field that is the identity set to auto-increment. My issue is trying to determine when the field is incremented. Is the field incremented when I call an instance of the object, when I call the AddObject method of the ObjectContext class, or when I call the SaveChanges method from an Entity model.
In my relational database each table has both a unique ID for that table and one that represents a group of users. After I create an instance of an object for that table I want to run a query (LINQ) that searches two tables to match two records and from one of those tables copy that group ID back to the individual user.
That or it is blatently obvious I know nothing about how relational databases work,
The identity field is handled by the database. It is created by the database when the row is inserted. The generated id is read back by SaveChanges and the entity object is updated.
WHen you add a new row to the database the counter is incremented.
If you have an ambiguity, this usually means that two tables fields are the same name, and your query doesn't know which one you want. Can be solved by defning which table the column is ment for.
I don't know LINQ, so hopefully someone can give you a more direct answer.

Updateable view in mssql with multiple tables and computed values

Huge database in mssql2005 with big codebase depending on the structure of this database.
I have about 10 similar tables they all contain either the file name or the full path to the file. The full path is always dependent on the item id so it doesn't make sense to store it in the database. Getting useful data out of these tables goes a little like this:
SELECT a.item_id
, a.filename
FROM (
SELECT id_item AS item_id
, path AS filename
FROM xMedia
UNION ALL
-- media_path has a different collation
SELECT item_id AS item_id
, (media_path COLLATE SQL_Latin1_General_CP1_CI_AS) AS filename
FROM yMedia
UNION ALL
-- fullPath contains more than just the filename
SELECT itemId AS item_id
, RIGHT(fullPath, CHARINDEX('/', REVERSE(fullPath))-1) AS filename
FROM zMedia
-- real database has over 10 of these tables
) a
I'd like to create a single view of all these tables so that new code using this data-disaster doesn't need to know about all the different media tables. I'd also like use this view for insert and update statements. Obviously old code would still rely on the tables to be up to date.
After reading the msdn page about creating views in mssql2005 I don't think a view with SCHEMABINDING would be enough.
How would I create such an updateable view?
Is this the right way to go?
Scroll down on the page you linked and you'll see a paragraph about updatable views. You can not update a view based on unions, amongst other limitations. The logic behind this is probably simple, how should Sql Server decide on what source table/view should receive the update/insert?
You can modify partitioned views, provided they satisfy certain conditions.
These conditions include having a partitioning column as a part of the primary key on each table, and having a set on non-overlapping check constraints for the partitioning column.
This seems to be not your case.
In your case, you may do either of the following:
Recreate you tables as views (with computed columns) for your legacy soft to work, and refer to the whole table from the new soft
Use INSTEAD OF triggers to update the tables.
If a view is based on multiple base tables, UPDATE statement on the view may or may not work depending on the UPDATE statement. If the UPDATE statement affects multiple base tables, SQL server throws an error. Whereas, if the UPDATE affects only one base table in the view then the UPDATE will work (Not correctly always). The insert and delete statements will always fail.
INSTEAD OF Triggers, are used to correctly UPDATE, INSERT and DELETE from a view that is based on multiple base tables. The following links has examples along with a video tutorial on the same.
INSTEAD OF INSERT Trigger
INSTEAD OF UPDATE Trigger
INSTEAD OF DELETE Trigger

What is a View in Oracle?

What is a view in Oracle?
A View in Oracle and in other database systems is simply the representation of a SQL statement that is stored in memory so that it can easily be re-used. For example, if we frequently issue the following query
SELECT customerid, customername FROM customers WHERE countryid='US';
To create a view use the CREATE VIEW command as seen in this example
CREATE VIEW view_uscustomers
AS
SELECT customerid, customername FROM customers WHERE countryid='US';
This command creates a new view called view_uscustomers. Note that this command does not result in anything being actually stored in the database at all except for a data dictionary entry that defines this view. This means that every time you query this view, Oracle has to go out and execute the view and query the database data. We can query the view like this:
SELECT * FROM view_uscustomers WHERE customerid BETWEEN 100 AND 200;
And Oracle will transform the query into this:
SELECT *
FROM (select customerid, customername from customers WHERE countryid='US')
WHERE customerid BETWEEN 100 AND 200
Benefits of using Views
Commonality of code being used. Since a view is based on one common set of SQL, this means that when it is called it’s less likely to require parsing.
Security. Views have long been used to hide the tables that actually contain the data you are querying. Also, views can be used to restrict the columns that a given user has access to.
Predicate pushing
You can find advanced topics in this article about "How to Create and Manage Views in Oracle."
If you like the idea of Views, but are worried about performance you can get Oracle to create a cached table representing the view which oracle keeps up to date.
See materialized views
regular view----->short name for a query,no additional space is used here
Materialised view---->similar to creating table whose data will refresh periodically based on data query used for creating the view
A view is a virtual table, which provides access to a subset of column from one or more table. A view can derive its data from one or more table. An output of query can be stored as a view. View act like small a table but it does not physically take any space. View is good way to present data in particular users from accessing the table directly. A view in oracle is nothing but a stored sql scripts. Views itself contain no data.
A view is simply any SELECT query that has been given a name and saved in the database. For this reason, a view is sometimes called a named query or a stored query. To create a view, you use the SQL syntax:
CREATE OR REPLACE VIEW <view_name> AS
SELECT <any valid select query>;

Resources