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

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.

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)

Customized Table Names in Sql Server

I have a table called Table 1. I'm trying to create an after-insert trigger for a Table 1; whereby, whenever a user enters a record, the trigger will create a new table named after the record that triggered its creation.
Please help, I'm using SQL Server 2008
This sounds super non-relational-database-design-ish. I would heavily advise against this in almost every case. And I say "almost" only to allow for artistic freedom of development, I can't think of a single case where this would be appropriate.
That said, if you do in fact want this, you can use dynamic SQL to create a table.
You can build the SQL in your trigger, but basically you want something like:
EXEC 'CREATE TABLE ' + #tableName + ' (ID INT IDENTITY(1,1))';
Of course, the columns are up to you, but that should get you started.
But while we're at it, what you should (probably) be doing is using a single table with a one-to-many relationship to the table on which your trigger is currently assigned.
For instance, if you have a table Users with a column for email and you're looking to create a table for each user's favorites on your website, you should instead consider adding an identity column for user IDs, then reference that in a single UserFavorites table that has UserId and PostId columns, and the appropriate foreign keys implemented.

cannot delete and update records on access linked table

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.

Syntax Error in From Clause deleting MSystem table records, relationship issue

I am looking to delete a relationship that was created with code in an Access 2007 DB, using vb.net. The DB may have been upgraded from an older level.
So here is what has been done, I open the DB with ADO connection string, the db is encrypted and password protect, I also open in Mode =12, to get exclusive rights. This all works. I grant SELECT, DELETE, and ALTER permissions on MSysObjects, and MSysRelationships to admin user.
The issue is the relationship used is a GUID, it is stored in these System tables as only text, but it can not be deleted from the tables for which the relationship was made, ie.
ALTER TABLE [MyTable] DROP CONSTRAINT '{D86827C0-some-GUID-6A6449F1FB07}';
or
ALTER TABLE [MyTable2] DROP CONSTRAINT '{D86827C0-some-GUID-6A6449F1FB07}';
This fails becuase the GUID can not be found on the table, I have tried the tables on both sides of the relationship. I am able to get the szRelationship value, which is how I have it to apply to the above ALTER query, yet as stated, it is not found as a relationship name on either table. This led me to believe that the DB may have been migrated from older Access. The System Object tables show this relationship, so I know it exists and it appears in the Relationships diagram. It can also be deleted there manually. I have hundreds of DBs that needs this edit though.
So my alternate approach was to delete directly from the two system tables.
DELETE [MSysObjects], [MSysRelationships] FROM [MSysObjects]
INNER JOIN [MSysRelationships]
WHERE [MSysObjects].[Name] = [MSysRelationships].[szRelationship]
AND [MSysObjects].[Name] = '" & relationName & "';
But this returns a Syntax error on the From Clause. I have searched high and low for alternative statements to try and to debug this one, with not luck...This link provided some samples and a starting point for syntax.
delete from two tables in one query
As it turns out the syntax error on my alter statement needed these [ ]....
ALTER TABLE [MyTable] DROP CONSTRAINT [{D86827C0-some-GUID-6A6449F1FB07}];
Works now.

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.