MS Access not working after swapping ODBC linked table with ODBC linked view - sql-server-2005

My company uses an SQL Server database, with Access as a front end. One of the biggest tables on the server is called tbl_Contacts. The primary key, "ContactID" was setup as an auto-incrementing "int" data type. Turns out yesterday afternoon, the limits of the "int" type ran out, and no new contacts could be added to the table.
At first I tried just updating the data type to "bigint", but then Access couldn't recognize the data type and showed "Deleted" for all the fields in the Contacts table.
I read a bunch of different articles and realized that Access 2010 cannot understand the bigint data type, and that I would need to cast the field to a different type that Access could understand.
I ended up making a View of tbl_Contacts and used this SQL to modify the ContactID field, including all the other fields in the table as is.
CAST(ContactID AS Decimal(15, 0)) AS ContactID
I then renamed the old linked table in Access to tbl_Contacts_OLD, added the new ContactsView table into Access with an ODBC connection, and renamed the View to "tbl_Contacts".
I thought everything was working, because I could add new records to the table again, but it turns out some things are still not working.
The only thing I can imagine is that other tables in my database are expecting "ContactID" to be a "Long Integer", and they aren't liking it being a "Decimal".
When I try to use a form that adds data to a table "tbl_CallLog", which links to "tbl_Contacts", I get this error.
Run-time error '3101'
The MS Access database engine cannot find a record in the table 'tbl_Contacts' with key matching field(s) 'ContactID'
Is there another data type I should be casting to that Access 2010 can recognize and use? Is there maybe a step I still need to do, perhaps casting the decimal value to yet another data type within Access?
Do I need to convert the data type on all other tables that reference the original Contacts table so they're linked fields are now decimal data types?

BigInt can be understood only by Access 2016.
The data types for a record id should be either Long or GUID. Long is by far the most commonly used.

So this isn't the best solution in the world, but I finally got my problem fixed doing the following.
My tbl_Contacts table only has 99k records in it, but due to various reasons, and the table being 20 years old, the IDENTITY SEED was at 2+ billion, the limits of the "int" datatype. I looked through the IDs and found a gap of 120k numbers, so I used this query to reset my seed value.
DBCC CHECKIDENT ('[tbl_Contacts]', RESEED, -92801);
GO
I've created several test contacts now, and the first one had the ID number -92800.
This should hold me until I can get a new CRM system in place in the middle part of the year.
Thanks for the comments, Gustav.

Related

Cakephp 3 with SQL Server 2012

I am writing RESTful API using cakephp 3.6 for SQL Server 2012. Some API's created and working fine.
But unfortunately not for one table. This table have primary key but its value is not auto incremented. When I am assigning its value API its generating error
SQLSTATE[23000]: [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Cannot insert the value NULL into column 'Id', table 'AccountsLive.dbo.Books'; column does not allow nulls. INSERT fails
I can't keep its primary key auto incremented.
When I create view to add it from browser. It does not create field for Id field. Then I try to create input field for Id field, its not going to display it on books input form.
Please help me to solve this issue, I will be thankful to you.
The assumption is that your id columns will be auto-incrementing. If there's a good reason(*) why you can't do that here, you'll need to add the input field (as you found), and also add it to the _accessible list in the Book entity.
(*) The number of situations where having your id column not auto-incrementing (and not a UUID) makes sense is really very small. Be very sure that this really does apply to you, as it moves all responsibility for avoiding overwriting records due to duplication onto you instead of the database.

Sql table Default Value

Hi everyone i have a project i am working on that consists on keeping tables the same at 3 different locations
i pull data that doesnt exist from each of these locations into a corporate table, i then need to send back down to the locations the new data so they are all the same
The table i am pulling from is a identity
My question is in Sql is there any way to make a table a identity without making it a identity as in setting the default value to be the max(id)+1, this is the only way i can figure i can keep the data structure the same without going to replication
The problem is that you're generating records in an IDENTITY field in multiple sources, then unable to combine them without those records being assigned new IDENTITY values.
By using a GUID as your key field, each of the 3 databases can create records which will have a unique ID, and you'll be able to then combine them without issue. You can still have a UNIQUE constraint on the field, but the likelihood of generating the same GUID is astronomically small.
Most replication processes utilize this GUID approach at some level already, so it's a common solution to this problem.

Is INT the correct datatype for ABS(CHECKSUM(NEWID()))?

I'm in the process of creating unique customers ID's that is an alternative Id for external use.
In the process of adding a new column "cust_uid" with datatype INT for my unique ID's,
When I do an INSERT into this new column:
Insert Into Customers(cust_uid)
Select ABS(CHECKSUM(NEWID()))
I get a error:
Could not create an acceptable cursor. OLE DB provider "SQLNCLI" for linked server "SHQ2IIS1" returned message "Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.
I've check all data types on both tables and the only things that has changed is the new column in both tables.
The update is being done on one Big #$$ table...and for reasons above my pay grade, we would like to have new uid's that are different form the one's that we currently have "so users don't know how many accounts we actually have."
Is INT the correct datatype for ABS(CHECKSUM(NEWID())) ?
For a moment, forget your issue with what must be an attempt to insert into a linked server (though it is not obvious from your code that Customers must either be a synonym or you dumbed the statement down).
Ask yourself: why would you use random numbers for uniqueness? Random and unique may seem like similar concepts, but they're not.
I also see a lack of error handling (again, this may just be that you dumbed down your code to "help" us). Eventually you will get duplicates. You may want to read this tip and this blog post. Essentially, as you insert more and more "unique" values, the likelihood that you will get a collision increases. So rather than solve the issue with your solution, I think you should step back and re-consider the problem.
Why are you using random numbers instead of simpler concepts that - at least by default - help assure uniqueness in a much more predictable way, like IDENTITY or SEQUENCE? Is it to prevent people from guessing the next value, or being able to determine how many values you generate in a time period? If so, then pre-populate a table with a bunch of random values, and pull one off the stack when you need one, as I described here. If this isn't the crucial issue, then stop breaking your back and just use an existing methodology for generating unique - and not random - numbers.
The update is being done on one Big #$$ table...and for reasons above my pay grade, we would like to have new uid's that are different form the one's that we currently have "so users don't know how many accounts we actually have."
Pick a constant and XOR it into the existing identifier to get yourself a somewhat obfuscated number. XOR it again to get the original identifier back.
Again bad choice for generating a unique ID
But with that said this does not throw an error so I think something else is going on
declare #id int
set #id = ABS(CHECKSUM(NEWID()))
print #id
Your update that you don't want users to know how many accounts and custID is an identity should have been in the original problem statement.

Converting Access db to SQL

Currently I'm performing a migration from a microsoft access database to an SQL Express 2010 database.
Basically, I have an Access application that searches a customer database. The access app is developed in 2 parts. An access front end on each client called application.mdb and a data backend on a windows 2008 server called data.mdb. The application.mdb has 3 linked tables to data.mdb. which holds customers and contracts and items. The customer table relates to the contracts table (one to many) and the contracts table relates to the items table (one to many)
I imported the tables from the data.mdb into the sql tables by the same name and created the same relationships and configured them to cascade. I then created an obdc connection on the clients and updated the 3 linked tables in application.mdb to point to the tables on the sql server.
I start the application and everything seemed to work great, I can see all the data perfectly and the performance increase was well worth the effort.
Then I found a problem, when I add a new customer to the database it autonumbers the customer table and the contracts table but not the items table.... Thus if I attempt to alters any of the items in the items table for new customers I can not. I get the following error "cannot add record(s); primary key for table "items" not in recordset" which makes sense because SQL had not autonumbered the items table.
I can't understand why....
Any help would be greatly appreciated.
Well, just manually adding record direct in the items view should tell you if the autonumber is working. You MUST get the autonumber working when you edit + use in direct table view.
As always these kinds of issues comes down to the details. One thing that's different when using a SQL based backend compared for access applications is the generation of auto numbers (primary key) does not occur on server based systems until record is actually saved. When working with the jet based back end, the auto number is available the instant the record is dirtied.
So I would check if you have some type of code or event running in the application that is attempting to use as primary key value before the record been actually saved.
Usually access does a pretty good job. For example when you build a form in access, and then have a sub form in access to edit child records (and a child table), then as a rule when the focus switches from a main form to a sub form, access will force a save of the main record. This thus means the primary key (auto number column) is now available for correct functioning of the relationship. Access can and will use this PK value and insert this value into the foreign key value column in this child table for you.
However access will only do above for you WHEN you correctly set up the link master and link child settings in the sub form control. As a general rule when building forms in regular access, Access can detect the settings required and insert the correct values into the link master and link child settings for you. However, the detection of the FK column will not occur with linked tables.
So when you use SQL server, you have to edit and set these values manually in the sub form control. So I would check your link master and link child settings in the sub form you're using to edit this data, and ensure that the correct values are set. If this is VBA code, then ensure the record is actually saved before attempt to use and grab a PK value.
I should point out that even in non SQL server based applications, it is the setting up of the link master + child settings in the sub form that allows access to setup and maintain this foreign key value for you. So access is always had the ability to insert these values for you, and it'll do so with you about having to write any code at all. So during the editing process to insert and maintain these values Access does all of the work for you (so it's not the data engine that inserts these FK values for you, but the user interface or in some cases code you write)
So access will not setup and insert these correct values unless you set up the link master + child settings in that sub form control.
I would simply check if your link master and child master settings are correct in any sub form control you are using here.
This sounds like a stupid answer but check the Items table to be sure that auto-numbering is turned on.
One of the things I would suggest whenever you migrate a Jet/ACE database to SQL Server is to thoroughly review the database design, e.g.: the implementation of keys and constraints, choice of data types, choice of indexes, etc. Jet/ACE is a very different thing to most SQL DBMSs so you shouldn't assume that a database design that worked well for Jet/ACE is automatically suitable for a SQL DBMS. Upsizing wizards won't always identify every possible issue.
In SQL Server the nearest equivalent of an "auto-number" is the IDENTITY property. Check to be sure which columns are IDENTITY in your tables and create an IDENTITY column if you need one.

Creating an ADO.NET Entity from primary key-less view (or stored procedure)

Using either a view and/or stored procedure, I can return the results of executing an MDX query against SQL Analysis Services (using OPENROWSET against a linked SSAS Server into SQL).
Unfortunately, the resultset doesn't include a PK field...or for that matter, even a column which COULD act as a PK if I were to hack the model.
Can anyone think of a hacktacular trick I can use to:
Add a field to my result which inserts some auto-incrementing value (to act as a PK candidate)
Somehow set this field to be the PK so that I can easily build an entity off of it?
I'm 99% sure the answer is "no". At this point I can already get data back from SSAS by using an SSRS report with OData rendering...but I have to create my types manually when I use play w/ LINQ.
If someone can nail #1 & #2 for me, this may be a potentially better way to access the data since the Modeler would create my types (entities) for me.
Thanks!
I'm not sure I understand why you can't have a column that could act as a primary key. I just ran a similar query against one of my cubes filtered to a list of members and each column name contained the member name. Here is an example:
Submission:
SELECT Measures.members ON ROWS,
Customer.[CustomerIdKeyField].[UniqueCustomerId] ON COLUMNS
FROM [Postage Prints]
Returned:
(colum header) [Measures].[MeasuresLevel].[MEMBER_CAPTION] [Customer].[CustomerIdKeyField].&[UniqueCustomerId]
(row) Measure1 9.6800000000000015
(row) Measure2 22
(row) Measure3 1