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

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)

Related

Deleting objects from SQL Server

In SQL Server Database Engine I have a table named Table A.
I deleted the table using graphical interface, but when I wanted to create a table with same name, the error shows
The object already exists
What is the remedy of this situation?
The following steps should help you track down what is going on and help you create your table:
Right-click on your database and select refresh
Verify that your table does not exist under this database.
If you table is
not shown here, then very likely your table is displayed under the
master database.
To create a table in your selected database,
first select the database and then run your query.
A better
option for number 4, just to be sure you are specifying the correct
database is to run the command use dbname; (where dbname is
the name of your database). Do this on the line above your create table code.

How to use SQL Server Temporary table #tblTmpYaks in Microsoft Access VBA?

I need to create a local temporary table #tblTmpYaks, then select records in this temp table to show in a PassThrough Query.
The temporary table is created as this:
CREATE TABLE #tblTmpYaks (ID INT NOT NULL IDENTITY,
YakName CHAR(30),
PRIMARY KEY (ID));
INSERT INTO #tblTmpYaks (YakName) VALUES('My Yak');
INSERT INTO #tblTmpYaks (YakName) VALUES('My Female Yak');
And then a passthru query is created with the SQL string:
SELECT * FROM #tblTmpYaks;
But this does not work, as show the MsgBox when I open it:
That means that the #tblTmpYaks does no more exist in the SQL Server.
How to make this work ?
Conclusion added a Posteriori
As Gord Thompson states below, I abandon the use of local temporary table #tblTmpYaks that lives only during a local SQL Server Session. Instead, a Global temporary table is used here noted ##tblTmpYaks, it can be implied in the RecordSource of an Access report through a passthrough query, and more it will be automatically deleted when one quits the Access Interface.
In a similar fashion to the question here, you'll probably have better luck if you use a SQL Server global temporary table (##tblTmpYaks instead of #tblTmpYaks). If you create the table via a CREATE TABLE Pass-Through query in Access then the table should persist until you close Access (unless you explicitly DROP TABLE first).

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.

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.

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.