Sorry if this is a newbie question.
Situation : I have a local SQL Server linked to a main SQL Server (reason, I don't have access to create views/sps/etc on main server)
I have defined views1, views2, views3 on local SQL Server which entirely relates tables/views on the main server (NO local SQL Server tables)
Q: how will a join on view1 and view2 or view3 materialize? That is, will the results of each view be pulled into the local server and joined locally (even though all referenced tables are on the main server)? Are there any guarantees one way or the other, OR is it entirely up to the optimizer ?
Q: if the view referenced a UDF on the local server, [ how ] would the process above change ?
Many thanks.
If all the tables involved in the query are on the same remote server (and that server is an Microsoft SQL Server), the JOIN operation should be performed remotely. To find out if it is executed locally or remotely, you can look at the execution plan (it should contain only a "Remote Query", no joins) or use Profiler on the remote server (if you have sufficient rights).
If the JOIN operation is perfomed locally, you may be able to change the query plan if you use the REMOTE JOIN hint (although this hint only makes sense if one of the tables is a local one). Getting an efficient query plans depends on having updated statistics and in the case of a distributed query (joining a local table to a remote table), this also means having enough rights to read the remote statistics: "If the linked server is an instance of SQL Server, to obtain all available statistics, the user must own the table or be a member of the sysadmin fixed server role, the db_owner fixed database role, or the db_ddladmin fixed database role on the linked server".
Related
I have a SQL database and I want to link an Access table in the SQL database. Most of the online articles and videos show how to link the two databases from Access but not from SQL. I want the access table linked in SQL database so that every time the table gets updated in Access, the table in SQL server gets updated as well. Thanks!
You can do that. It's called a Linked Server and will link your Access database in SQL Server where you typically will create a view to read the Access tables to avoid the DatabaseName..TableName syntax otherwise needed.
However, it will probably not work for you because SQL Server will insist on opening the linked Access database exclusively, meaning that you cannot open it later from your Access application. And if you open it first in Access, an attempted reading from SQL Server will fail because SQL Server cannot get exclusive access.
You may argue, that a shared access should be possible, and connection parameters indicate this, but I haven't found a way to achieve this.
So, as others have mentioned, you may have turn this upside/down, and use, say, ODBC to link the SQL Server tables in your Access application, and then let this take care of the maintenance of the SQL Server tables.
It must be like this (SQL SERVER) => (MS Access)
and yes you are correct, it's called linked tabled in Ms Access. In order to link a table from another database, you must have
Correct drivers installed. (ODBC)
Know the login details of your SQL server and have sufficient permission in SQL server
Go to MS Access -> External data -> ODBC Databse -> link to the data source by creating a linked table ->
Now you can select a DSN file where your sql server credentials are saved, or you can make "new" and follow the steps to get connected to the SQL server.
Once connected, you will be presented with a list of all the tables from SQL server. Select the table you want to link and finish the wizard.
You now have SQL table connected in MS Access and can input data directly.
I'm new to SQL Server and trying to automatically update tables in SQL Server from tables in MS Access.
I have an Access database of metadata that must be kept updated for sending records to other groups. I also have a database in SQL Server which also has these same metadata tables. Currently these tables in the SQL Server database get updated manually by exporting the Access tables as Excel files, and then importing them into the SQL Server tables.
It's not the most efficient process and could lead to errors in the SQL Server database if someone forgets to check that they are using the most recent data from Access. So I would like to integrate some of the tables from Access to my database in SQL Server. Ideally I would like for the tables in my SQL Server database to be updated whenever Access is updated or at least update the tables automatically in the SQL Server database when I open it.
Would replicating the Access tables be the best? I am using SQL Server 2014 Developer so I think I have this capability. From my understanding, mirroring is for an entire database not just pieces of it. However, I do not want to be able to alter the metadata from SQL Server and have it reflected in Access. I cannot tell if reflecting the tables would do this...?
I also looked at this post about writing multiple insert statements but was confused (What is the best way to auto-generate INSERT statements for a SQL Server table?). Someone else suggested importing all the data into SQL Server and then using an ODBC driver to connect the two, but I'm also not sure how this would update the database in SQL Server anytime Access is updated.
If you have any suggestion and a link to easy to follow tutorial I would really appreciate it!
Thanks
In Access, go to 'External Data', ODBC Database, and connect to the SQL Server database directly - make sure you select 'Link to the data source by creating a linked table' on the first page of the wizard. Now, this linked table is available in Access, but is actually the SQL Server table.
Get rid of the local Access tables, using the new linked tables in their place in whatever queries, forms, reports, etc that you have in Access.
Now, any changes to the tables you see in this Access db ARE changes to the SQL Server database.
in my company, we have several environments with MS SQL database servers (SQL 2008 R2, SQL 2014). For the sake of simplicity, let us consider just a TEST environment and a PROD environment and two sql servers in each. Let the servers be called srTest1, srTest2, srProd1, srProd2 and each be running a default MS SQL Server instance. We work with multiple databases, say DataDb, ReportDb, DWHDb.
We want to keep the same source code in T-SQL for both TEST and PROD, but the problem is the architecture or distribution of the above mentioned databases in each environment:
TEST:
srTest1 - DataDb
srTest2 - DWHDb, ReportDb
PROD:
srProd1 - DataDb, ReportDb
srProd2 - DWHDb
Now, say, in ReportDb, we write stored procedures with many SELECTs referencing tables and other objects in DataDb and DWHDb. In order to have source code as universal as possible, we decided to create linked servers for each database on each db server in each environment and name them with respect to the database they're created for. Therefore, there'll be these linked servers:
lnkDataDb, lnkReportDb and lnkDWHDb on srTest1,
lnkDataDb, lnkReportDb and lnkDWHDb on srTest2,
lnkDataDb, lnkReportDb and lnkDWHDb on srProd1,
lnkDataDb, lnkReportDb and lnkDWHDb on srProd2.
And we'll adjust the source in the stored procs accordingly. For instance:
Instead of
SELECT * FROM DataDb.dbo.Contact
We'll write
SELECT * FROM lnkDataDb.DataDb.dbo.Contact
The example above is reasonable for a situation where the database from which you execute the query (ReportDb) lies on a different server than that with the referenced table (DataDb). Which is the case for the TEST environment. But not so in PROD. It is performance I'm here concerned about. The SQL Server will treat that SELECT as a "remote query" no matter whether, in fact, it is a reference to a local object or not.
Now, it comes the most important part:
If you check these 3 queries for their actual execution plans, you'll see an interesting thing:
(1) SELECT * FROM DataDb.dbo.Contact
(2) SELECT * FROM srProd1.DataDb.dbo.Contact
(3) SELECT * FROM lnkDataDb.DataDb.dbo.Contact
The first two (query #1 and #2) have the same execution plan (the fastest possible) even if you use the four-part name manner of referencing the table Contact in #2.
The last query has a different plan (remote query, thus slower).
The question is:
Can you somehow create a linked server to self (the same sql server instance, the default instance actually) as an "alias" to the name of the host (srProd1) in order for the SQL server to be forced to understand it as local and not issue "remote execution" plans?
Thanks a lot for any hints
Pavel
Recently I found a workaround which seems to solve this kind of issues more efficiently and more elegantly than the solution with self-pointing linked servers.
If you work (making reports, for example) with multiple databases on multiple SQL servers and the physical distribution of the databases on the servers is a challenge since it may differ from one environment to another (e.g. TEST vs PROD), I suggest this:
Use three-part db object names whenever possible. If the objects are local, then execution plans are also local, and thus effective.
Example:
SELECT * FROM DataDb.dbo.Contact
If you happen to run the above query from within a different SQL server instance (residing on a different physical machine, for example, but this not necessarily, the other SQL server instance could be installed even on the same machine), briefly if you're about to use a four-part name:
SELECT * FROM lnkDataDb.DataDb.dbo.Contact
Then you can circumvent that using the following trick:
Let's assume lnkDataDb points to srTest2 and you're executing your queries from srTest1. Now, you'll create a "fake" database DataDb on your local server (srTest1). This fake DataDb shall contain no real db objects (no tables, no views, no stored procedures, no UDFs etc.). There shall only be synonyms defined in it. (And there also shall be the same schemas in it as those in the real DataDb on srTest2). These synonyms shall be named exactly the same way as their real db-object counterparts in DataDb on srTest2. Example:
-- To be executed on srTest1.
EXEC sp_addlinkedserver
#server = N'lnkDataDb',
#srvproduct = N'',
#provider = N'SQLNCLI',
#datasrc = N'srTest2'
;
GO
CREATE DATABASE [DataDb];
GO
USE [DataDb];
GO
CREATE SYNONYM dbo.Contact FOR lnkDataDb.DataDb.dbo.Contact;
GO
Now, if you want to SELECT rows from the table dbo.Contact residing in the database DataDb on srTest2 and you're executing your query from srTest1, you'll use a simple three-part table name:
SELECT * FROM DataDb.dbo.Contact
Of course, on srTest1, this is not a table, that's just a synonym referencing the same-named table on srTest2. However, that's the trick, you use the same query syntax as if you were executing it on srTest2 where the real db object resides.
There are disadvantages of this approach:
On the local server, at the beginning, there must not be a database
with the same name as the remote one. Because you're about to create
a "fake" database with that name to reflect the names of remote
db objects.
You're creating one database that is almost empty, thus
increasing the mess of various databases residing on your local
SQL server. This might provoke reluctance of your database admin
if they prefer having as few databases as possible.
If you're developing your T-SQL scripts in SQL Server Management
Studio, for example, using synonyms cuts you off from the convenience
of the IntelliSense feature.
Advantages outweigh the above-mentioned disadvantages, though:
Your scripts work in any environment (DEV, TEST, PROD) without
the need to change any part of the source code.
If the other database you're querying data from resides on the same
SQL server instance as your script, you also use the three-part name
convention and your SQL server evaluates the query in execution plan
as local which is OK. (This is what the original question of this
post was searching to solve.)
If the other database you're querying data from resides on another
SQL server instance, you still use a "local syntax manner" of a SQL
query (with the synonym) which, only at runtime, evaluates in
a remote execution plan. Which is also fine because the db object
actually is remote.
To summarize
The query executes as local if the referenced object is local, the query executes as remote if the referenced object is remote, but the T-SQL script is always the same. You don't have to change a letter in it.
I'm trying to save the values of several columns of one table to another table on a different server. I am using SQL Server. I would like to do this without running external programs that query from this database and insert the results into the new database. Is there any way to do this from within the SQL Server Management Studio?
This is a recurring event that occurs every hour. I have tried scheduling maintenance tasks that execute custom T-SQL scripts but I'm having trouble getting the connection to the remote server.
Any help would be appreciated.
If you can set up the remote server as a linked server you should be able to configure the SQL Server Agent to execute jobs that contain queries that access tables on both the local and linked server. Remember that you might have to configure the access rights for the account used to run SQL Server Agent so that it has permissions to read/write tables on both servers.
This practice might not be without issues though as this article discusses.
You can use a 4 part name like;
INSERT [InstanceName].[DatabaseName].[SchemaName].[TableName]
SELECT * FROM [SourceInstanceName].[SourceDatabaseName].[SourceSchemaName].[SourceTableName]
But first you will have to set the remote server as a linked server as so;
https://msdn.microsoft.com/en-us/library/aa560998.aspx
Subquestioning [1] and [2].
Where does SQL Server store server objects?
And why there?
Update:
This question is defined as subquestion and in context of cited questions...
Should I understand the answer that sql_policy_trigger, shown under Server Objects\Triggers in Object Explorer of SSMS (MS SQL Server R2), is stored in master database?
=====Update2:
Please give me the references to msdn docs in your answer(s).
It is not obvious that system or server configuration objects, meta-information or catalogs are stored in database(s). For ex., FTS catalog is not stored in database but in file (system), etc.
[3] (BOL2005-2008R2) tells that:
"master Database
Records all the system-level information for an instance of SQL Server"
"In SQL Server, system objects are no longer stored in the master database; instead, they are stored in the Resource database"
So, it is instance-wide (but not server-wide) and it clearly mentions "system".
As well as it hints that "they" are not stored in master database.
Also, I would like to understand why SSMS permits to script server objects (for ex., right-click in Object Explorer under Server Objects --> Triggers on syspolicy_server_trigger --> Script Server Trigger as...---> ) while, for ex., system views do not have such possibility.
Cited:
[1]
Where does a Server trigger save in SQL Server ?
Where does a Server trigger save in SQL Server?
[2]
“system objects” vs. “server objects” in SQL Server - terms definitions?
"system objects" vs. "server objects" in SQL Server - terms definitions?
[3]
master Database
[3a]
(SQL Server 2008 R2 Books Online)
http://msdn.microsoft.com/en-us/library/ms187837.aspx
[3b]
(SQL Server 2005 Books Online)
http://msdn.microsoft.com/en-us/library/ms187837(v=SQL.90).aspx
sys.objects, sys.indexes etc (as per your trigger question). See Object catalog views in MSDN
As for why, a relational database may as well use a relation structure to store information about itself, no? Apart from a few registry settings used on start up, almost every setting and object is stored in a table somewhere in SQL Server.
Examples:
sys.messages = error messages
sys.configurations = sp_configure
Edit, I had to dredge my memory about why this is so...
Rule zero in Codd's law
The system must qualify as
relational, as a database, and as a
management system. For a system to
qualify as a relational database
management system (RDBMS), that system
must use its relational facilities
(exclusively) to manage the database.
This ignores the "relational" puritans and zealots but explains why sys.objects etc are used.
Edit:
Making a guess at what OP really wants... server level objects are stored in the master database.