I have just noticed that one of the views I create from Microsoft Access in SQL Server via a linked server is interpreted differently in different machines/setups etc.
Example:
EXEC sp_addlinkedserver acc465tghv, 'OLE DB Provider for Jet', 'Microsoft.Jet.OLEDB.4.0', 'C:\tester.mdb'
EXEC sp_addlinkedsrvlogin acc465tghv, TRUE
GO
CREATE VIEW TI265 AS SELECT * FROM acc465tghv...TI0CE
When I open the access database in a different machine/computer, the date is formatted differently and I am sure other data types may be formatted/interpreted different when you open the same database (.mdb file) in different machines/computers with different versions of Access and setups etc.
The question is, how can I create a view or a table that shows the access table exactly the same in SQL server?
What options or work arounds are there?
Thanks all
This is pretty standard SQL Server behaviour, based on some functions being deterministic and others non-deterministic. You can read up a bit more about the various functions here.
You can also use SET DATEFORMAT to specify the format in which strings are interpreted by SQL Server.
However, in this scenario, it's pretty likely that the client machine is the thing that is formatting the date differently, based on it's Locale.
Related
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 am new to MS SQL and I am trying to do something that seems simple but is driving me crazy.
I want to write a query to pull data from two databases. Each database is on a different instance on the same DEV machine. (one is MS SQL 2008 and the other MS SQL 2005). I am using the Microsoft SQL Server Management Studio (MSSMS).
I have the basics figured out. I know the format of the query and what I need to do. My big problem is figuring out what the NAME of each server is?
SELECT LastName
FROM [servername1].CHA2.dbo.Customer
UNION
SELECT LastName
FROM [servername2].OBXKites.dbo.Contact
ORDER BY LastName
I used the server name that I connect to MSSMS (DLPT\HENRY) with and what is also returned by ##SERVERNAME
SELECT ##SERVERNAME returns DLPT\HENRY
I tried
DLPT\HENRY.CHA2.dbo.Customer
did not work
I tried it without the DLPT HENRY.CHA2.dbo.Customer
did not work
I need to future out what the NAME of the server is to use in the query.
[DLPT\HENRY].CHA2.dbo.Customer
The namo contains a backslash which is normally illegal in an identifier. You surround illegal names with brackets.
Note that you surround just the server name. In other words, it is [DLPT\HENRY].CHA2.dbo.Customer, not [DLPT\HENRY.CHA2.dbo.Customer].
You have to configure Linked servers. Then only different instances of SQL Server are able to communicate with each other.
Unfortunately you can't access tables in databases in separate SQL Server instances by default. You have a couple of options here - neither are simple and might require help from a DBA:
1) Use linked servers like this:
http://technet.microsoft.com/en-us/library/ff772782(v=sql.110).aspx
Then you will be able to refer to the second table in the format INSTANCENAME.DatabaseName.SchemaName.TableName
2) Use replication to get the table from the second database into the first database. Then the contents of the second table will be synched to the first database in more or less real time
Read about SQL Replication here
We have several SQL servers set up in my workplace that are all linked to each other and we make use of 4-part DB names in a lot of our code. We are considering moving some of our databases from one server to another and are assessing the impact on our code, however no one here seems to know beyond the Linked Server Name what protocol is used in the [server] portion of the 4pt DB name [server].[database].[dbo].[table]. Is the [server] portion a WINS entry, is it simply DNS, or is SQL Server doing something clever on it's own to get there?
If it's DNS, it will be simple enough to move the DB's (minimal code changes), but anything else and we may have to reconsider our strategy.
server is just a symbolic name, the datasrc is what really matters.
Suppose you have a linked server created like this:
EXEC master.dbo.sp_addlinkedserver #server = N'TEST', #srvproduct=N'', #provider=N'SQLNCLI', #datasrc=N'server2008r2'
and the queries select from TEST.database.schema.table. Recreate the linked server with different #datasrc and it will still work, but this time it would read data from a different physical server (as long as the data is there and the security is set up right).
In SQL Server, you can apply the use function to point a query to another database. For example:
USE databasename
GO;
Is there a function that allows you to point to a different database server and use a database on that server? I would expect this to work, but no luck:
USE [servername].databasename
GO;
I know I could just point the query to the database on the other server, but when I am dealing with production versus staging environments, it's more efficient to declare the server and database in the beginning of the query.
Thanks
USE does not span across to another server, you need to define a linked server on your local instance and then you can access data from that server.
I use Linked Servers to accomplish this. I don't know if this will meet your needs, however.
http://msdn.microsoft.com/en-us/library/ms188279.aspx
In Management Studio, this is available under Database/Server Objects/Linked Servers.
You can refer to objects on this server like this:
[Server].database.schema.object
I just realized this isn't what you want. JonH has it right, you can't specify a dabase on another server at the beginning of your query.
I'm working on a desktop application that must support (currently) MS Access and SQL Server back ends. The application is under constant development and changes are frequently being made to the database, mostly the addition of tables and views to support new features (but also some DROPs and ALTER TABLEs to add new columns).
I have a system that compiles the DDL into the executable, checks the database to see if the executable has any new DDL that has to be executed, and executes it. This works fine for a single database.
My immediate problem is that SQL Server and Access support wildly different names for data types so a CREATE TABLE statement that executes against Access will not execute against SQL Server (or worse, will execute but create a table with different datatypes).
Is there a method that can be used to create DDL (especially CREATE TABLE commands) that can be executed through ADO against both of these databases without having to craft separate DDL for each provider?
Since you are already using ADO, you should look into Microsoft ADOX
This allows you to manipulate structures in a data source using an ADO object model that is independent of the underlying data source type. i.e. without resorting to explicit DDL
Support for ADOX is not guaranteed by any given ADO Provider, and the level of ADOX support may vary even when it is available. But for MS Access and MS SQL Server I think you will find all the capability you require (and quite possibly more!)
This can be done using DBX in Delphi.
The following is links to sample code showing how this can be done.
http://cc.embarcadero.com/item/26210
I had the same problem.
I resolved it applying a C preproccessor to the SQL before executing it.
The preprocessor includes macros in order to handle the different dbs.
Stefano
Did you check
http://db.apache.org/ddlutils/
or
http://publib.boulder.ibm.com/infocenter/wtelecom/v6r1/index.jsp?topic=%2Fcom.ibm.twss.plan.doc%2Fdb_scripts.html