I am trying to update a #temp table from a linked server using a top clause but am getting a very odd result - it seems to be ignoring the order by in my code.
I can fix the specific problem programatically but would like to know if this is a one off issue or there is a general problem with the way i have linked the servers.
The query is being run on a 2005 SQL Server (9.0.3042) linked to a 2008 SQL Server R2 (10.50.279) linked via the Microsoft OLE DB Provider for SQL Server.
The query looks like this - i have already created #TempTable which has the columns Id, Date and PrevDate and inserted data into the Id and Date columns.
update #TempTable
set PrevDate =
(select top 1
d.Date
from
linkedserver.DB.dbo.Date as d
where
d.Id = #TempTable.Id
and d.Date < #TempTable.Date
order by
d.Date desc)
The select is not picking the top 1, it appears to be picking the first date entered into the table for the specific Id and ignoring the order by clause.
When I just do a select, it works fine
When I put in the PrevDate via the inital insert, it works fine.
When I use a Max rather than a Top, it works fine.
When I run the exact same query/scenario on the 2008 SQL Server via a link (same provider) back to the 2005 SQL Server, it works fine
I am not looking for a fix for this specific query but would like to know if this is an isolated incedent or some fundamental problem with 2005 to 2008 linking that is going to manifest itself in very hard to find ways.
Thanks,
Tim
I have some bad news. I have replicated this issue here. It looks to me to be an issue with SQL Server 2005's query plan (I tested with a later version too, v 9.0.4035):
Image: Query plan for update statement
(sorry I can't embed images here, not enough reputation)
The details for that remote query:
Image: Remote Query details
There is no ORDER BY statement sent to the remote server, so the results that come back are indeed just the TOP (1) in an arbitrary order, which is likely to be in the order of the primary key. It seems to me that SQL Server should have emitted an ORDER BY Date desc there.
Therefore, I have to conclude that other queries like this, in this environment, could easily have the same issue (so, not an isolated incident).
By the way, there is a Microsoft Connect issue already raised for this one, from 2009: connect.microsoft.com/SQLServer/feedback/details/446017/missing-order-by-in-remote-query-with-update-statement
Related
A view that references a remote server
4part name ([ServerName], [DatabaseName], [Owner], [Object Name]
OpenQuery
Which is better performance?
Why is performance good?
AFAIK, it depends a lot on your remote server type.
With recent SQL version (2016) on both server (local and remote), I didn't noticed any difference.
If your remote server is anything else (postgres, mysql...) your really should use OpenQuery as it executes the query on the remote server, getting only the correct resultset. If you use the 4 part name, SQL server will order and filter on local.
For example, take a 4 million record table and execute a query like :
SELECT * FROM reoteserver.database.schema.table where id = 4
With openquery, sql server will get only the record with id 4. Without, it will get all the table, and then filter it to get the id 4.
Late to the party here, but the difference essentially is that 4 part queries are executed locally, thus cannot utilise indexes or keys since the local server doesn't know about them. Instead it essentially retrieves the entire object, then applies the filter. On a small table, you would be unlikely to notice a difference, but on a table with millions of rows, you'd notice a difference. Openquery essentially tells the remote server to execute the query on it's behalf then pass the result back.
General rule I would say is;
NEVER join on to a table using 4 part. Only join using Openquery and I would even avoid that where possible, but that's more of a personal preference.
However, 4 part SP execution i.e. EXEC ServerName.DBName.SchemaName.ObjectName is essentially the same since that also tells the remote server to execute the query on its behalf.
Have a need to filter any and all SELECT statements against a particular table in a SQL Server 2008 database. Basically need to add an an additional condition (or create one) to all SELECTS.
So the server receives a request for SELECT * FROM PRODUCTS, we need to change this to
SELECT * FROM PRODUCTS WHERE Condition = 1
I'm open to just about any solution, anyone have any thoughts on how to achieve this?
Not our program, this would be a modification to an ERP package at the database level.
Embedded CLR is an available option, if it helps
I have the following code:
select order_number,received_date
from order_head
where order_head.order_number not in (select order_number from csa_log group by order_number)
and ordernature in ('02','03')
and received_date > '01.01.2010'
and buyer_code = 'GAP'
group by order_number,received_date
order by received_date desc
When run in crystal reports does not pull the same data as sql server express. It is pulling only one record as opposed to 7. Anybody have some insight? Thank you in advance. (I have a suspicion it has something to do with the nested statement).
Several possibilites come to mind.
First are you absolutely sure that Crystal Reports and the database you are querying are the same one. Amazing how often one is querying dev and another prod when you have these kinds of issues. Even if you don't believe this to be the case, check this anyway.
Permissions could be another reason for the discrepancy.
Finally confirm that the two queries are exactly the same. Use Profiler if possible to confirm this.
Usually I use SQL server profiler to check what SQL Statements Crystal is running behind the scenes. In your case is not possible because you are running SQL Server Express.
In Crystal you have the option of checking the actual SQL statement that Crystal is running by selecting "Database" and "Show SQL Statement" in the top menu.
Make sure that under Reports menu you are not putting any conditions in the Select Records.
Check that you are showing the fields in the detail and not in the header or footer. That is a common mistake.
I am using MS SQL Server 2000 and have a link from a test db to a live db which is in replication. The link seems to work fine and I can select from any of the tables using any of the fields apart from the field with the constraints on creating ids. So if I run
select * from person where firstname like 'john' this works fine, but then if I run select * from person where id =1 then I get no data returned and I get no errors but the record exists.
Any advise is much appreciated.
Thanks
If select * from person where id =1 returns no rows then the record doesn't exist.
It's been a few years since I've worked with linked servers, but have you tried running profiler against the linked server (the live DB) to see that it's receiving the select statement and that it's receiving it correctly?
Can you see the record in enterprise manager through the dblink, or are you looking at the linked db directly?
Maybe your link is not pointing where you think it is.
i have a view that is using linked server to retrieve data from a remote server in SQL Server. On each time viewing the view, the results returned are vary. For example, 1st time execution may return 100 rows of records but on 2nd time of execution, rows returned are 120 rows. Any ideas what is the cause?
I have witnessed odd linked-server results that are a product of non-determinism written into the SQL itself, I.e. a TOP query written without an ORDER BY clause.
This problem, for example, where the chap had multiple non-unique foreign keys coming from a table source on the left hand side of a linked-server INNER JOIN, and wanted 10 rows from a remote sub-query to the right, where the end result was restricted to 10 rows itself, when it should have been greater than 10 rows.
Should definitely give your SQL a quick eye for such curiosities.
The data on the linked server changed between executions?
Is your SQL Server fully patched? SQL Server 2008 and 2005 both have bug fixes out related to incorrect query results from linked servers.
Here is one example:
969997 FIX: You receive an incorrect result when you query data from a linked server that is created by using an index OLE DB provider in SQL Server 2005 or in SQL Server 2008
Is the linked server also a SQL Server? If not, perhaps a buggy driver? I've seen odd results, for example, due to an old Informix ODBC driver. Are you able to run something akin to SQL Profiler on the linked server to see what command it's receiving?
I'm not sure what the answer is, but (assuming that your counts of 100 and 120 are accurate) can you not capture the data from the two runs and compare it? That might give you some clues as to what's going on. For example, is it completely different datat, or is it duplicate rows (in the 120 row batch).