1

I have this weird behavior of Schema Compare in Visual Studio 2017.

  1. When comparing 2 databases, two identical tables I get difference that one of those has no PK name. If I would script out tables using SSMS I would see that indeed on one of the servers table script seems not to have PK name, but if I would query sys.indexes table I can find that this index has a same name on both of the servers.

    One possible solution I found is to update the table, let's say add some random index and remove it, so I am guessing that it has something to do with how SQL Server stores the objects definition. But it would be nice to know what is causing this and how to solve it in the right way and not with some kind of workarounds.

    PK_Diff

    p.s. I know that the PK name is not "correct".

  2. Similar situation when comparing two identical SPs. I tried to run sp_refreshsqlmodule and sp_recompile but it didn't help. Updating SP helps, but again this is not very nice workaround.

    SP_diff

EDIT 1: In the first example PK with the same name exists on both databases (even though the name is not following standards). The following query ran on both databases returns identical result:

SELECT I.name 
FROM sys.indexes AS I
INNER JOIN sys.objects AS O
    ON O.object_id = I.object_id
INNER JOIN sys.schemas AS S
    ON S.schema_id = O.schema_id
WHERE S.name = 'MySchema'
AND O.name = 'MyName'

Result: PK__TraceDat__AAAC09D801ED28A5

Ramūnas
  • 1,494
  • 18
  • 37

2 Answers2

1

Both things you're noting are due to bad practices on the scripts, and are concrete issues that could cause issues down the line. While right now there may be no immediate issues, there can be on the future.

In the first case, you've pointed out the root problem, there is no name for the PK in the left side, while there is some name on the right. Actually, all constraints always have a name, you can indicate it explicitly and it will be the name. But if the creation script doesn't indicates a name (like your left side) the server will create a random name for the constraint (that's what you're seeing on the right side). This is a problem because different servers will have different names for the constraint (if there are multiple instances of the DB) and you won't have a concrete name to refer to the constraint if you later want to remove or change it. The real solution is simple, just give a name to the constraint yourself, so it have a fixed reference.

The second case is even worse. The only difference is that the left side has a procedure without a schema, while the right side it's explicitly defined as dbo. Every object within a database lives within a schema, and when one isn't explicitly indicated, the default schema of the user is used to determine it. There are a variety of reasons why that is a bad practice (for one, in a multischema DB there is a chance of ambiguity or choosing the wrong table, performance is also negatively affected), so the solution is to simply name the proper schema when creating or modifying tables (querying is also important too, although unrelated here).

Alejandro
  • 7,290
  • 4
  • 34
  • 59
  • I totally agree that those are bad practices, no arguments there, but: 1. There is a PK in both databases and it is identical (see EDIT 1), just the Schema compare for some reason recognize this as different. 2. As you mentioned object cannot be without schema and if I would query the system objects I would see that it belongs to the `dbo` schema. I am interested in why `Schema Compare` engine flags these as a difference. – Ramūnas Apr 10 '18 at 11:55
  • In both cases the answer is that *"because they are different"*. In 1, having the constraint differing only by name means that they work the same right now, but change scripts must be different (to cope with the changed name), so that's a difference. In 2, the missing schema means that the real schema assigned on creation can be different according to te DB settings, again creating non-deterministic change scripts afterwards. By being explicit in both cases you ensure that no matter the context you always get the same DB. – Alejandro Apr 17 '18 at 11:00
  • 1. The name is the same. Please read the EDIT 1. The name is not following conventions, yes, but it is the same on both databases. And the change script would be identical for both. (tested it) 2. It can, but it is not. In this case the default schema is `dbo`. – Ramūnas Apr 20 '18 at 14:01
0

I sometimes have similar issues using Apex sql diff after renaming objects. Try drop/create instead. It is potential reason of problem.

Juozas
  • 916
  • 10
  • 17