cannot delete and update records on access linked table - sql

I have access database called road.mdb.
Inside road.mdb, I have a linked SQL table and
the table name is student.
I can insert records using query design in MSAccess
But I cannot update nor Delete
when run delete query below, the error is: could not delete from specified table
delete from student where studentid=303;
and when I run update query below, the error is: Operation must use an updateable query
update student set Name='BOB' where studentid= 303;
I have full access to the sql database and I can run the query OK using sql management studio.
Is it impossible to delete and update using query design inside MSaccess??
The weird thing is I can insert new records using query design inside MSaccess
thank you

I SOLVED this by adding primary key to the SQL table and re linked the table to ACCESS
Thanks everyone...

In the case that you can't manipulated the table on SqlServer, you can get around the problem by telling Access which/s column/s are meant to be the primary key. This is done on the last step of creating a Linked table, the window title is "Select Unique Record Identifier".

You will find that the following steps will most likely solve your problem:
In SQL Server: set a primary key on the table you are working with and make sure the primary key is of type int, not bigint as Access will not properly deal with bigint data type.
In SQL Server: refresh the table.
In MS Access: re-link the table.
(You can easily check if 'things are OK' afterwards by adding a record to the SQL Server table and accessing it through the MS Access linked table. When all is OK you should not see #Deleted when viewing the data from MS Access side.)
Hope it helps ;-)

In my case, the linked table only had keys. I had to modify one of the keys to be a primary key and then I could truncate truncate the table via a DELETE table.* FROM table via access.

In my case the problem was a BIT column. I think the problem occurs when the the bit column contains a NULL value.
To resolve the issue, I either deleted the entire column, or set a default value.

Related

Access ODBC can't pull from SQL table with more than 255 columns

I have a database that I'm trying to query from Access with ODBC. The table I need to read from has 304 columns, and I can only see the first 255 in the Query Builder. I've read elsewhere that the solution is to write an SQL query by hand rather than relying on the Builder, so I tried this query:
SELECT [Field1], [Field304]
FROM [ODBC;DRIVER=SQL Server;UID=USERNAME;SERVER=ServerAddress].[TabelName];
This query returns Field1 just as I'd expect, but still won't get Field304. What am I doing wrong?
You have encountered a limitation of ODBC linked tables in Access, and a query like
SELECT ... FROM [ODBC;...].[tableName];
is really just a way of creating a temporary ODBC linked table "on the fly".
When Access goes to create an ODBC linked table it queries the remote database to get the column information. The structures for holding table information in Access are limited to 255 columns, so only the first 255 columns of the remote table are available. For example, for the SQL Server table
CREATE TABLE manyColumns (
id int identity(1,1) primary key,
intCol002 int,
intCol003 int,
intCol004 int,
...
intCol255 int,
intCol256 int,
intCol257 int)
an Access query like
SELECT [id], [intCol002], [intCol255]
FROM [ODBC;DRIVER={SQL Server};SERVER=.\SQLEXPRESS;DATABASE=myDb].[manyColumns];
will work, but this query
SELECT [id], [intCol002], [intCol256]
FROM [ODBC;DRIVER={SQL Server};SERVER=.\SQLEXPRESS;DATABASE=myDb].[manyColumns];
will prompt for the "parameter" [intCol256] because Access does not know that such a column exists in the SQL Server table.
There are two ways to work around this issue:
(1) If you only need to read the information in Access you can create an Access pass-through query
SELECT [id], [intCol002], [intCol256]
FROM [manyColumns];
That will return the desired columns, but pass-through queries always produce recordsets that are not updateable.
(2) If you need an updateable recordset then you'll need to create a View on the SQL Server
CREATE VIEW selectedColumns AS
SELECT [id], [intCol002], [intCol256]
FROM [manyColumns];
and then create an ODBC linked table in Access that points to the View. When creating the ODBC linked table remember to tell Access what the primary key column(s) are, otherwise the linked table will not be updateable.
Thanks Gord! That solves the problem of update large tables from within Access.
If anyone is interested, I've created a view inside sql server, selecting only the fields I wanted, then I link it inside Access.
Now, any update made in this link, reflects to the original table. So it's easy to do this running querys.
Super easy fix on my end
click start menu
search 'ODBC'
click 'system DSN' tab
highlight odbc and select 'configure'
click on 'advanced' tab
adjust maximum columns to 3000 (or some high number)

"operation must use an updateable query" for UPDATE query on SQL linked table in Access

In my Access database I have one temp table - msCurrentAnnualUpload and one linked to SQL server table - msCurrent.
After I try to run Update query I get an error ("operation must use an updateable query").
Text of query is the following:
UPDATE msCurrent
INNER JOIN msCurrentAnnualUpload ON (msCurrent.ProductID = msCurrentAnnualUpload.ProductID) AND (msCurrent.CountryCodeID = msCurrentAnnualUpload.CountryCodeID)
SET
msCurrent.Y1977 = msCurrentAnnualUpload.Y1977,
msCurrent.Y1978 = msCurrentAnnualUpload.Y1978,
msCurrent.Y1979 = msCurrentAnnualUpload.Y1979,
msCurrent.Y1980 = msCurrentAnnualUpload.Y1980
can you help me to find an issue??
I just copied and pasted your query into Access 2010 and it worked correctly. Verify that you can update the values in your linked table by opening it in Datasheet View and manually changing one of the [Y1977] values. If you cannot update the linked table then you'll need to confirm that
Your ODBC connection actually has permission to UPDATE the table on the SQL Server.
Your Access linked table has a Primary Key defined. (Open the Access linked table in Design View and check for the little gold key icon(s) as in the screenshot below.)

Why is one of my SQL tables not allowing me to update in spreadsheet view in MS Access?

Situation:
I have quite a few tables created in SQL
These tables are linked to MS Access
I can very easily "add" new entries to all but one of the tables
This table includes a Foreign key reference (but so do others)
All tables are created the same way and linked the same way
Problem:
I cannot add entries in the Spreadsheet View in Access. Generally you have some sort of entry like (where there is a * as well as empty row beneath the table you can click in and begin typing)
However this table looks like:
Right clicking on a record has "New Record" and "Delete Record" grayed out, while I can use this on other tables
I am creating the table using:
CREATE TABLE ProjectApprovers (
ProjectCode varchar(50) FOREIGN KEY REFERENCES ProjectCodes(ProjectCode),
RACFApprover varchar(50)
);
The reason I am confused is that it does not appear to be a SQL permissions problem because I can run the following code in Access:
INSERT INTO ProjectApprovers (ProjectCode,RACFApprover) VALUES ('ValidProjectCode','test123');
It seems these restrictions are only limited to the spreadsheet view. Additionally, identical syntax is used to create other tables which do not have this problem.
I am using this code to link my database tables.
Is something like this a permission problem? I have never referenced this problem table with permissions.
If Access doesn't recognize a primary key in the linked table, it will present the table as read-only in Datasheet View.
Fix this by adding a primary key in SQL Server. Then recreate the link in Access so it can notice the changed table structure.

How do I create a table alias in MySQL

I am migrating an MS Access application (which has linked tables to a MSSQL Server) to MySQL.
As a means to overcome some MSAccess table naming problems, I am seeking a solution to add a MySQL table alias that will point to an existing table in the MySQL database. Ideally I would like to create the alias 'dbo_customers' in mysql that would point to the customers table also in mysql.
To be clear I am not wanting to alias a table name inside a query like this:
SELECT * FROM customers AS dbo_customers
But rather I would like to be able issue the following query:
SELECT * FROM dbo_customers
and have it return data from the customers table.
Off the top of my head
CREATE VIEW dbo_customers AS
SELECT * FROM customers
Maybe not the best solution but should work as the view is updatable. Will definitely work for Read Only
You can create a View.
CREATE VIEW dbo_customers AS SELECT * FROM customers;
If that doesn't work for you, you could try creating a shadow-copy of the table, and use Triggers to keep the tables synced.
For example:
CREATE TABLE t1( id serial primary key, field varchar(255) not null );
CREATE TABLE dbo_t1( id serial primary key, field varchar(255) not null );
-- INSERT trigger
CREATE TRIGGER t1_dbo_insert AFTER INSERT ON t1
FOR EACH ROW BEGIN
INSERT INTO dbo_t1 SET field = NEW.field;
-- No need to specify the ID, it should stay in-sync
END
-- UPDATE trigger
CREATE TRIGGER t1_dbo_update AFTER UPDATE ON t1
FOR EACH ROW BEGIN
UPDATE dbo_t1 SET field = NEW.field WHERE id = NEW.id;
END
-- DELETE trigger
CREATE TRIGGER t1_dbo_delete AFTER DELETE ON t1
FOR EACH ROW BEGIN
DELETE FROM dbo_t1 WHERE id = OLD.id;
END
Not exactly an 'alias', and far from perfect. But it is an option if all else fails.
there is a simpler solution for MySQL via MERGE table engine:
imagine we have table named rus_vacancies and need its English equivalent
create table eng_vacancies select * from rus_vacancies;
delete from eng_vacancies;
alter table eng_vacancies ENGINE=MERGE;
alter table eng_vacancies UNION=(rus_vacancies);
now table rus_vacancies equals to table eng_vacancies for any read-write operations
one limitation - original table must have ENGINE=MyISAM (it can be easily done by "alter table rus_vacancies ENGINE=MyISAM")
You could create a view named dbo_customers which is backed by the customers table.
#OMG Ponies ponies said in a comment:
Why not rename the table?
...and it seems the obvious answer to me.
If you create an ODBC linked table for the MySQL table customers it will be called customers and then all you have to do is rename the table to dbo_customers. There is absolutely no need that I can see to create a view in MySQL for this purpose.
That said, I'd hate to have an Access app that was using SQL Server table names when the MySQL tables were not named the same thing -- that's just confusing and will lead to maintenance problems (i.e., it's simpler for the linked tables in the Access front end to have the same names as the MySQL tables, wherever possible). If I were in your position, I'd get a search and replace utility and replace all the SQL Server table names with the MySQL table names throughout the entire Access front end. You'd likely have to do it one table at a time, but in my opinion, the time it takes to do this now is going to be more than made up for in clarity going forward with development of the Access front end.
I always rename my "linked to SQL" tables in Access from
{dbo_NAME} to {NAME}.
The link creates the table name as {dbo_NAME} but access occasionally has problems with the dbo_ prefix.
Aliases would be nice, yet MySQL does NOT have such a feature.
One option that may serve your needs, besides creating a view, is to use the FEDERATED storage engine locally.
CREATE TABLE dbo_customers (
id INT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT '',
PRIMARY KEY (id),
)
ENGINE=FEDERATED
DEFAULT CHARSET=latin1
CONNECTION='mysql://fed_user#localhost:9306/federated/customers';
There are currently some limitations with the FEDERATED storage engine. Here are a couple especially important ones:
FEDERATED tables do not support transactions
FEDERATED tables do not work with the query cache
I'd like to mention a bad solution I explored (and abandoned), which was to use hardlinks on the .frm, .MYD and .MYI files corresponding to my table in /var/lib/mysql/{name_of_my_database}/.
It does, however, NOT work. For InnoDB tables, it simply cannot (even if you hardlink the .idb file) because tables are also referenced in ibdata1.
For MyISAM tables, it kind of works, except it doesn't because in memory, the tables are still distinct and thus do not share cache. So if you write a row to original_table, it won't immediately appear in aliased_table. You would have to flush tables first… which defeats the purpose and even causes data loss (if you insert a row in both the original and the alias before flushing, only one row is kept).
I thought my experiment was worth mentioning as a cautionary tale.

Are writing triggers in MS SQL server the same as writing them in MS Access?

I have written the following trigger in SQL server:
create trigger test_trigger
on invoice -- This is the invoice table
for insert
as
declare #invoiceAmount int -- This is the amount specified in the invoice
declare #custNumber int -- This is the customer's id
--use the 'inserted' keyword to access the values inserted into the invoice table
select #invoiceAmount = Inv_Amt from inserted
select #custNumber = cust_num from inserted
update customer
set amount = #invoiceAmount
where Id = #custNumber
Will this be able to run in MS Access or is the syntax different?
The Access database engine (formerly called Jet) does not have triggers and regardless has no control-of-flow syntax e.g. a PROCEDURE must consist of exactly one SQL statement.
Tell us what you really want to do and there could be an alternative syntax.
For example, you could create a new key using a UNIQUE constraint on invoice, (cust_num, Inv_Amt), a FOREIGN KEY customer (id, amount) to reference the new key, a VIEW that joins the two tables on the FOREIGN KEY columns and exposing all four columns, then INSERT into the VIEW rather than the table 'invoice'; you may want to use privileges to prevent INSERTs to the base table but user level security was removed from the new Access 2007 engine (called ACE).
But, if you don’t mind me saying, I think your trigger doesn't reflect a real life scenario. A column vaguely named 'amount' in table 'customer' to hold the most recent invoice amount? What about when the inserted logical table contains rows for more than one customer? As I say, I think you need to tell us what you are really trying to achieve.
Access doesn't have triggers
Your trigger that you show here will bomb out since it does not take into account multirow updates the moment someone updates more than one row (and don't say it won't happen because it will better to practice some defensive coding)
Triggers fire per batch not per row, please read Multirow Considerations for DML Triggers
join inserted pseudo table and the invoice table instead to update the values...that works for 1 and more than 1 row
They may be coming in Access 2010? http://blogs.msdn.com/access/archive/2009/08/13/access-2010-data-macros-similar-to-triggers.aspx
MS Access doesn't have triggers.
That is, the the Access Jet engine (which creates .mdb files). If Access is connecting to a database server, then it will use whatever triggers are in that database.
I've never come across triggers in Access unless it's dealing with ADP on SQL Server. So your answer is yes, it's the same if you're on SQL Server for the backend, and no if the table is stored in Access.