Why does view become read only when linked to Access? - sql-server

In SQL Server Management Studio, I created both indexed and regular (non indexed) views. When I updated the data, the base table's data was changed as well. However, when I link my views to Access using VBA or using Access GUI linked tables I need to specify a index. If I do not do so the view will be read only.
Why is non indexed view read only in Access but not in SQL?

I personally found it very difficult to digest the accepted answer and work out what the problem was and how to resolve it.
Why aren't linked views editable?
Essentially, SQL Server views do not have a Primary Key (PK) and, therefore, are considered read-only (non-updateable) by MS Access because MS Access requires a unique column to use for updates.
How to edit the data in a linked view
A UNIQUE INDEX must be created in MS Access after the view has been linked.
For example, if the table is called dbo_table and the PK column in SQL is called id, create a new query and paste the following into it:
CREATE UNIQUE INDEX myPK ON dbo_table (id ASC)
The word myPK is the name of the index (this can be renamed if needed). Execute the query.
The linked view will now be updateable.
The reference documentation for MS Access CREATE INDEX is available here.

Well, first of all, when you use the Access GUI to link to a table, it NEVER prompts you for an index, it prompt you for the primary key. So let’s get that crazy and silly misinformation corrected like REAL fast, shall we?
When you link to a SQL server view, you get this prompt:
That above prompt is not asking you for a index.
The reason why access does this is because it needs a PK to update a linked table, or a linked view.
PROBLEM:
SQL server does not have a PK defined for a view. And SQL server DOES NOT LET YOU SPECIFY a PK for a view. If SQL server had some way to define a PK for a view, then Access could use that information to grab the PK.
However, since views don’t have a PK on sql server, then when linking to such Views YOU THE HUMAN have to choose a PK.
Access linked tables are read only without a PK.
Access linked views are read only without a PK.
However, sql server views do NOT have a PK defined.
Again:
SQL server views do NOT have a PK defined.
If you create the linked view with VBA code, then no GUI prompt appears asking you for the PK. You can tell Access which column is to be “assumed” as the PK by executing a local create index command. This command DOES NOT ACTUALLY CREATE a index. It does not create one server side, and it does NOT create a actual working index on the access client side.
All the create index command does is tell access what PK column to use. So you not actually creating a index in this case.
Again:
SQL server views do NOT have a PK defined.
If SQL server allowed one to create or set a PK for a view, then Access could simply use that information and know what PK to use, and then set it for you.
However (and again)
SQL server does not have a PK defined for a view.
However for the access client to update a linked table, it needs a PK. When linking to a table, Access can simple ask SQL server what column is the PK. However, you cannot ask SQL server
“what is the primary key” of a view.
(however, you can for a table).
So you not creating a index in Access (it does nothing since a index on the client side of access with a linked table, or a linked view is NOT a working index and does NOTHING!!! (except provide a place to tell access what colum is the PK). It is NOT working index nor is it even a real index.
The existence of an index in Access for linked tables/views does not actually create a working index – only that some “extra” information such as if a PK exists in the table is stored when you “create” that index.
Again: Access does not create indexs for linked table. When you execute create index on a linked table A INDEX IS NOT CREATED IN THIS CASE. ONLY INFORMATION ABOUT THE TABLE OR VIEW IS STORED LOCAL IN ACCESS.
Again: you not creating a index.
Again:
If sql server had a feature or option to define a PK for a view, then no doubt Access would also use that information. However, views in sql server don’t have a defined PK, and thus Access can’t use the PK, and if access can’t find a PK, then it assumes the table is read only.
The SQL management studio can often update tables without a PK, but Access has to use ODBC to connect to sql server, and ODBC has FAR LESS features then SSMS when connecting to a database.

Related

Trying to use a composite unique index instead of a composite unique identifier

I am evaluating outsystems and am trying to write a PoC List/CRUD app based on a legacy database table (the structure of which cannot be changed) which does not have a primary key but instead has two text fields that together constitute a unique index. The database is SQL Server 2014.
The table is successfully added in Integration Studio using "Connect to External table or view".
Then when I open the TestApp in Service Studio and go to the data tab I see the entity there, but it's not usable because it has no identifier defined. I have read some online info that I can double click on the entity and go to the Indexes tab. Here I normally would expect to see the index already defined in the database but it's not there. I also expect to the the New and Delete buttons to be enabled so I can create and delete indexes but New is disabled.
Am I correct to assume that OutSystems should have already "seen" the existing composite unique index? If so, am I correct to assume that this index would have sufficed to create a pseudo/virtual identifier for the entity, whereby making the entity system happy for CRUD and List operations? And also why is the New button not enabled for me to even manually create the index?
Can someone help me please in the correct direction?
Thanks
The OutSystems platform only supports single primary keys, so you have to create the CRUD operations by hand.
For external entities, index information is not fetched from the database, and the reason you can't create the index is because OutSystems doesn't control the metadata (i.e. you can't create indexes, create/modify columns, etc).

SQL Server Tables Relationship in Access

I connected a sql server through ODBC and lined sql tables. I manually created my relationships in my database but, when I do that, my other tables are not editable. My drop downs I created won't allow me to select it or my text box doesn't let me type in it.
How am I supposed to create a relationship so I can use Access as a front-end to enter in data into the database?
If you are linking to tables that exist already in SQL Server, then you don't need to worry about creating relationships in Access.
If you want to edit data in the SQL Server tables, make sure that you have a primary key on each table, and if possible a field with at "timestamp" data type.

MS Access shows #deleted, although data is saved correctly

We have an MS Access 2007 database with a MS SQL Server 2008 backend.
On the server, for each table, we have written a view, and each view contains triggers for update/insert/delete. These views are then linked into MS Access as linked tables.
Every server table contains a primary key consisting of one or more columns, plus a separate IDENTITY column (int, with unique index).
Now, if I go into MS Access and enter data directly into the linked table, everything works fine.
But if I create a Form, which uses the linked table as recordsource, then after each insert, all fields show #deleted. However, the data is stored correctly into the database, so it is mainly a display problem!
I think this has something to do with the triggers, but I cannot find the problem.
Can anyone help on this problem?
Problem solved. There was actually a problem in the trigger, which caused more than row to get updated or inserted. After fixing the trigger, everything works now.

Sql Server 2008 Replicate Synonym?

I plan on updating some table names by create a synonym of the old name and renaming the table to what I want it to be. Can replication properly reference a synonym?
Also as a side question, is there an easy way to see if a specific table is actually being replicated? (via a query perhaps)
I don't think so. Replication works by reading the log and there are no log records generated for a synonym. As to your question about finding out which tables are replicated, a query on sysarticles in the table should get you where you want to go. HTH.

Use SSIS to migrate and normalize database

We have an MS Access database that we want to migrate to a SQL Server Database with a new DB design. A part of the application that uses the SQL Server DB is already written.
I looked around to find out how to do the migration step most easily and started with Microsofts SQL Server Integration Services (SSIS). Now I have gotten to the point that I want to split a table vertically for normalization reasons.
A made up example looks like this
MS Access table person
ID
Name
Street
SQL Server table person
id
name
SQL Server table address
id
person_id
street
How can I complete this task best with SSIS? The id columns are identity (autoincrement) columns, so I cannot insert the old ID. How can I put the correct person_id foreign key in the address table?
There might even be a table which has to be broken up into three tables, where a row in table2 belongs to table1 and a row in table3 belongs to a row table2.
Is SSIS the appropriate means for this?
EDIT
Although this is a one-time migration, we need to have an automated and repeatable process, because the production database is under heavy usage and we are working on the migration in our development environment with recent, but not up-to-date data. We plan for one test run of the migration and have the customer review the behaviour. If everything is fine, we will go for the real migration.
Most of the given solutions include lots of manual steps and are thus not appropriate.
Use the execute SQL Task and write the statement yourself.
For the parent table do Select into table from table... then do the same for the rest as you progress. Make sure you set identity insert to ON for the parent table and reuse your old ID's. That will help you keep your data integrity.
For migrating your Access tables into SQL Server, use SSMA, not the Upsizing Wizard from Access.
You'll get a lot more tools at your disposal.
You can then break up your tables one by one from within SQL Server.
I'm not sure if there are any tools that can help you split your tables automatically, at least I couldn't find any, but it's not too difficult to do manually although how much work is required depends on how you used the original tables in your VBA code and forms in the first place.
A side note
Regarding normalization, don't go overboard with it: I know your example was just that but normalizing customer addresses is not always (rarely?) needed.
How many addresses can a person have?
If you count a home address, business address, delivery address, billing address, that's probably the most you'll ever need.
In that case, it's better to just keep them in the same table. Normalizing that data will just require more work to recombine and offers no benefit.
Of course, there are cases where it would make sense to normalise but I've seen people going overboard with the notion (I've been guilty of it as well) and then find themselves struggling to build more complex queries to join all that split data, making development and maintenance harder and often suffering a performance penalty in the process.
Access is so user-friendly, why not normalize your tables in Access, and then upsize the finished structure from there?
I found a different solution which was not mentioned yet and allows us to use all the comfort and options of the dataflow task:
If the destination database is on a local SQL Server, you can use a dataflow task with SQL Server destination instead of an OLE DB destination.
For a SQL Server destination you can mark the "keep identities" option. (I do not know if the english names are correct, because we have a german version.) With this you can write into identity columns
We found that we cannot use the old primary keys everywhere, because we have some tables that take a union of records from multiple tables.
We start the process by building a temporary mapping table with columns
new_id (identity)
old_id (int)
old_tablename (string)
We first fill in all the old_id s for every table that is referenced by a foreign key in the new schema. The new_id values are generated automatically by SQL Server.
So we can use a join to translate from old_id to new_id where needed. We use the new_id values to fill the identity (primary key) columns in the new tables with the "keep identities" option and can simply look them up in our mapping table for the foreign keys by a join.
You might also look at Jamie Thomson's SSIS Normalizer component. I just found out about it today (haven't actually tried it yet). The example he posts looks a lot like the one in your question.

Resources