Is it possible to force a field to always be a certain value?
We have a website in production that writes a value entered by the user into a string field. Now, our requirements have changed and we no longer actually want to save this value. For technical reasons, we don't want to do a new publish just for this if we don't have to.
What would be ideal is to ALTER the table in such a way that the field will always be NULL and that existing INSERTS and UPDATES into the field will work as normal but SQL Server will NULL the field regardless.
This is a temporary thing. We will eventually change the code to not write this value.
Just looking for a quick way to NULL the field without changing code, republishing etc...
Is this possible? Is writing a trigger the only solution?
Thanks!
You could make an INSERT and UPDATE after trigger that will NULL the field each time it is updated / inserted into.
This is the quickest and easiest solution.
Related
I'm getting the error message:
This record has been changed by another user since you started editing it. If you save the record, you will overwrite the changes the other user made...
I know this is a common question and I've spent hours researching and testing but to no avail. A few notes:
There are no bit fields anywhere in my database
All tables have a primary key, data type = identity
All tables have a create/modified timestamp trigger on updates and insert
I'm fairly certain that the problem has to do when the form (and multiple subforms) are creating the identity fields and/or the timestamp triggers. Specifically, I only get this error on the "Individual Fish" table when I go back to edit an old 'fish' (as shown on the screenshot). If I just tab through the form and don't make any edits, it works fine. But if I need to edit anything on a previous 'fish' - after the identity / trigger fires - then it gives me the error.
I've gone through and added If Me.Dirty Then Me.Dirty = False End If to every form for the following events:
On Current, On Load, On Click, After Update, Before Update, Before Insert, On Dirty.
I also added DoCmd.RunCommand acCmdSaveRecord to On Deactivate. I will admit that I am not great at VBA, so there could be something silly I did here. Code attached. I've also messed around with Record Locks = Edited Record.
So far nothing seems to work. Please let me know if you think I'm missing something. Also, if you have any random comments or suggestions about my database design or anything else, I always welcome feedback.
Thanks!
UPDATE:
Albert's answers got me to the right place. The short version is to add a rowversion (aka timestamp) field to all tables. This was mentioned on several other posts, but i didn't realize the [awfully named] "timestamp" didn't actually have to do with date or time. Thanks for the help!
]3
Ok, lots of things here to check. First of all, placing a me.Dirty = false in on-current, or events like before update will cause the "same" event to try and trigger again. You really (but really really) don't want to do this. (so wild random tossing in of me.dirty in those events will only make this issue much worse and often cause the very same event to trigger again.
next up:
All tables have a create/modified timestamp trigger on updates and insert
Ok, now the above is confusing. Do you have an actual trigger - as that is a separate issue and will often trigger the record been modified by someone else.
Also when we speak of a timestamp column, do keep in mind that such columns have ZERO ZERO ZERO to do with datetime. Over the years Microsoft has attempted to "change" the name used. The correct name is ROWVERSION, and this column is NOT a datetime data type column, but is called timestamp. Do NOT in ANY WAY confuse this rowversion system/column with that of a datetime column.
So, the assumptions are:
You have a timestamp column - this is of data type timestamp. This column is NOT touched by your code or trigger in ANY WAY. This column is NOT of datetime, nor of datetime2, but is of data type timestamp.
If you don't have a actual timestamp column here (it does not need to be on the form), then you will get constant "dirty" warnings. You also get this with any real data type columns - especially if they are set by server code. (access will round differnt).
Bottom line:
You need a actual rowversion column (of type timestamp) in that table. Behind the scenes if access does NOT find this column, then it will do a column by column compare, and without question with a trigger to set some LastUpdated column with GETDATE() on the server side trigger, then this will cause nothing but problems. Introduction of a timestamp column will STOP access from doing the column by column compare after a update, and it will ONLY look at the timestamp column. So, your trigger can now update the LastUpdated, and the timestamp column should not change from access points of view.
So, you need to be sure:
A PK column is seen by access - all sql tables need a PK.
All tables should have a rowversion column.
If you do add a timestamp (rowverison) column to the problem table, then make sure you re-link on the access client side. In fact after ANY table change or modifications server side, then you should re-link the client side.
I would remove any stray me.Dirty = False code in that form.
You can place a "save" button on the form if you wish, and simply have it go
if me.dirty = true then me.Dirty = False
Edit
With the above setup, you should be able to re-introduce your server side trigger that sets the LastUpdated. However, you not want any code in the form that "touches" or uses that column. You can however should be able to drop in that LastUpdated column into the form and see it update after you save.
Bottom line as I have run across this error on an upgrade of SQL Server to 2016, due not assume "timestamp" is of data type "datetime". It is not. The data type that Access requires is of type "timestamp". Add a column with that data type to any table that is editable through Access and that will clear the "Write conflict with grayed out save button" message.
I haven't had this problem until I first tried to manually add data to a database since my upgrade to WebMatrix 3, so I don't know if this is a bug or some kind of fault prevention.
I have defined a very simple table with the primary key as int and set it to not allow nulls, and be of the type IsIdentity so that the int value will automatically increment, as needed.
A pic of that is shown here:
Okay, seems simple enough, but when I try to manually add data to the table, it, as it should, does NOT allow me to modify the primary key value in any way (because it is automatic).
All I do is put in a couple of string values to the type and location columns and it tells me that it couldn't commit changes to the database because of the invalid value in the primary key field (it acts as though it is gonna try to throw NULL in as the value, but this should be overridden when it automatically adds the row. The user-interface does not allow me to control or edit this value in anyway).
A pic of this is shown here:
What is this? Some kind of bug? Is it a new rule that WebMatrix does not allow a developer to add values to the database manually? Do I have to write a query every time I want to add something to the database? Am I in the Twilight Zone? (Okay, sorry about the last one...)
Also, I've noticed that if I don't have IsIdentity set, I can edit the field, put a PERFECTLY VALID integer therein, and it still errors the same way, so I use ESC to backup my changes, then hit refresh, only to find that it did, indeed, add the row anyway :/ . So, this interface seems kind of buggy to begin with. In my scenario above (using IsIdentity), it DOES NOT add the row anyway, unfortunately.
--------------------UPDATE--------------------------
I just recently downloaded a WebMatrix update, and it appears that they have fixed this! Yay! (till now I was just querying generic INSERT INTO statements and editing them manually from there).
I think the SQL CE tooling with WM3 is broken, suggest you look at other tools for editing data - I can recommend the standalone SQL Server Compact Toolbox (disclosure: I am the author)
Need advice on what is the best approach to get the auto incremented id to be the same on multiple forms.
Basically I am using VB .Net with SQL Server as the backend. I wrote a few stored procedures to insert data and then I am calling the stored procedures on the front end. I have 3 forms and once the first form is submitted it generates an autoID and then takes the user to 2nd form.
In the second form I have a separate insert stored procedure is there a way to grab the id that the first form generated and for it to be consistent. Or should I store it in a variable after they submit the form and then call it in the second form.
I read about the ##Identity but that only grabs the id within that session since I am submitting the first forms data then going to the second wouldn't that be a different session.
Thanks
Your stored proc could return the identity value (use the output clause or scope_identity() to get it) as an output variable that you would store as a variable in your application, then it would be available to use. You would want to make sure to null out the varaible when the person moves to a differnt record and after allthe associated formas have inserted records, so that you don;t inadvertently use it at some other time.
You do not want to ever use ##identity for this as it is unreliable and can create massive data integrity issues as it will give you the wrong value if someone adds a trigger that inserts to another table with an identity.
The fact that this is causing you problems might be an indicator that this isn't the best way to do it. Perhaps instead, use a function on the DB to return the ID, and then set it in your .net code?
If you have an auto incremented ID, then it should only increment when a record is created. Are your three forms creating three records? Is that what you want? If so, then an auto ID is definitely not the right way to go.
I think maybe your over thinking this?
I read about the ##Identity but that only grabs the id within that session since I am submitting the first forms data then going to the second wouldn't that be a different session.
Don't you want the key that was generated by the entries made on the first form?
In the second form I have a separate insert stored procedure is there a way to grab the id that the first form generated and for it to be consistent. Or should I store it in a variable after they submit the form and then call it in the second form.
I am using entity framework to insert details into the database where I have a column varchar(50).
when I am trying to insert some value more than 50 length it gives me an error string or binary data would be truncated.So ., for safe side I just changed it to varchar(100).
Now can someone let me know is this the only solution to change the value in the Db or do we have any alternatives.......
I read an article http://sqlblogcasts.com/blogs/danny/archive/2008/01/12/scuffling-with-string-or-binary-data-would-be-truncated.aspx
But how can I use such things in c#. I appreciate any suggestions from you.........
Thanks
Depending on what type of input field you're dealing with, using varchar(max) could be an option.
But as previously pointed out, it really boils down to what your business requirements are.
Well, first of all, obviously you cannot insert a string longer than 50 in a varchar(50).
So you have two options depending on your requirement:
change the database (as you have found out) and make sure that all code 'upstream' will be able to tackle the longer data
add some validations or restrict user input so that you will never get a string that is longer
Well, there's a third and that is cut off the string without telling the user but I would not do that.
So it depends on your business requirement what to do. But I would not do any 'tricks' like in the article you suggested
You should set the field length in the db to whatever is a reasonable length and you should prevent users from entering values that does not fit within that length.
1-when database table Alter when issue generated
2-First Backup table schema and data then delete table when re create table then run code .. working fine.
I have a huge database (800MB) which consists of a field called 'Date Last Modified' at the moment this field is entered as a text data type but need to change it to a Date/Time field to carry out some queries.
I have another exact same database but with only 35MB of data inside it and when I change the data type it works fine, but when I try to change data type on big database it gives me an error:
Micorosoft Office Access can't change the data type.
There isn't enough disk space or memory
After doing some research some sites mentioned of changing the registry file (MaxLocksPerFile) tried that as well, but no luck :-(
Can anyone help please?
As John W. Vinson says here, the problem you're running into is that Access wants to hold a copy of the table while it makes the changes, and that causes it to exceed the maximum allowable size of an Access file. Compacting and repairing might help get the file under the size limit, but it didn't work for me.
If, like me, you have a lot of complex relationships and reports on the old table that you don't want to have to redo, try this variation on #user292452's solution instead:
Copy the table (i.e. 'YourTable') then paste Structure Only back
into your database with a different name (i.e. 'YourTable_new').
Copy YourTable again, and paste-append the data to YourTable_new.
(To paste-append, first paste, and select Append Data to Existing
Table.)
You may want to make a copy of your Access database at this point,
just in case something goes wrong with the next part.
Delete all data in YourTable using a delete query---select all
fields, using the asterisk, and then run with default settings.
Now you can change the fields in YourTable as needed and save
again.
Paste-append the data from YourTable_new to YourTable, and check
that there were no errors from type conversion, length, etc.
Delete YourTable_new.
One relatively tedious (but straightforward) solution would be to break the big database up into smaller databases, do the conversion on the smaller databases, and then recombine them.
This has an added benefit that if, by some chance, the text is an invalid date in one chunk, it will be easier to find (because of the smaller chunk sizes).
Assuming you have some kind of integer key on the table that ranges from 1 to (say) 10000000, you can just do queries like
SELECT *
INTO newTable1
FROM yourtable
WHERE yourkey >= 0 AND yourkey < 1000000
SELECT *
INTO newTable2
FROM yourtable
WHERE yourkey >= 1000000 AND yourkey < 2000000
etc.
Make sure to enter and run these queries seperately, since it seems that Access will give you a syntax error if you try to run more than one at a time.
If your keys are something else, you can do the same kind of thing, but you'll have to be a bit more tricky about your WHERE clauses.
Of course, a final thing to consider, if you can swing it, is to migrate to a different database that has a little more power. I'm guessing you have reasons that this isn't easy, but with the amount of data you're talking about, you'll probably be running into other problems as well as you continue to use Access.
EDIT
Since you are still having some troubles, here is some more detail in the hopes that you'll see something that I didn't describe well enough before:
Here, you can see that I've created a table "OutputIDrive" similar to what you're describing. I have an ID tag, though I only have three entries.
Here, I've created a query, gone into SQL mode, and entered the appropriate SQL statement. In my case, because my query only grabs value >= 0 and < 2, we'll just get one row...the one with ID = 1.
When I click the run button, I get a popup that tells/warns me what's going to happen...it's going to put a row into a new table. That's good...that's what we're looking for. I click "OK".
Now our new table has been created, and when I click on it, we can see that our one line of data with ID = 1 has been copied over to this new table.
Now you should be able to just modify the table name and the number values in your SQL query, and run it again.
Hopefully this will help you with whatever tripped you up.
EDIT 2:
Aha! This is the trick. You have to enter and run the SQL statements one at a time in Access. If you try to put multiple statements in and run them, you'll get that error. So run the first one, then erase it and run the second one, etc. and you should be fine. I think that will do it! I've edited the above to make it clearer.
Adapted from Karl Donaubauer's answer on an MSDN post:
Switch to immediate window (Ctl + G)
Execute the following statement:
DBEngine.SetOption dbMaxLocksPerFile, 200000
Microsoft has a KnowledgeBase article that addresses this problem directly and describes the cause:
The page locks required for the transaction exceed the MaxLocksPerFile value, which defaults to 9500 locks. The MaxLocksPerFile setting is stored in the Windows registry.
The KnowledgeBase article says it applies to Access 2002 and 2003, but it worked for me when changing a field in an .mdb from Access 2013.
It's entirely possible that in a database of that size, you've got text data that won't convert to a valid Date/Time.
I would suggest (and you may hate me for this) that you export all those prospective date values from "Big" and go through them (perhaps in Excel) to see which ones are not formatted the way you'd expect.
Assuming that the error message is accurate, you're running up against a disk or memory limitation. Assuming that you have more than a couple of gigabytes free on your disk drive, my best guess is that rebuilding the table would put the database (including work space) over the 2 gigabyte per file limit in Access.
If that's the case you'll need to:
Unload the data into some convenient format and load it back in to an empty database with an already existing table definition.
Move a subset of the data into a smaller table, change the data type in the smaller table, compact and repair the database, and repeat until all the data is converted.
If the error message is NOT correct (which is possible), the most likely cause is a bad or out-of-range date in your text-date column.
Copy the table (i.e. 'YourTable') then paste just its structure back into your database with a different name (i.e. 'YourTable_new').
Change the fields in the new table to what you want and save it.
Create an append query and copy all the data from your old table into the new one.
Hopefully Access will automatically convert the old text field directly to the correct value for the new Date/Time field. If not, you might have to clear out the old table and re-append all the data and use a string to date function to convert that one field when you do the append.
Also, if there is an autonumber field in the old table this might not work because there is no way to ensure that the old autonumber values will line up with the new autonumber values that get assigned.
You've been offered a bunch of different ways to get around the disk space error message.
Have you tried adding a new field to your existing table using Date data type and then updating the field with the value the existing string date field? If that works, you can then delete the old field and rename the new one to the old name. That would probably take up less temp space than doing a direct conversion from string to date on a single field.
If it still doesn't work, you may be able to do it with a sceond table with two columns, the first long integer (make it the primary key), the second, date. Then append the PK and string date field to this empty table. Then add a new date field to the existing table, and using a join, update the new field with the values from the two-column table.
This may run into the same problem. It depends on number of things internal to the Jet/ACE database engine over which we have no real control.