How to design an auto-increment field while allowing manual user input? - c#

The Client table:
Id (PK), int, not null (IDENTITY)
NoClient, int, not null
The form (wireframe):
The field NoClient should be a number
The field NoClient should be unique
The field NoClient should be auto-generated if null
The field NoClient is for reference only
The field NoClient is NOT the primary key
The field NoClient is NOT the identity column
How to solve that problem SQL-wise?
EDIT. I'm talking about the NoClient column, not ID.

Strictly interpreting those rules, there is no solution. One of those rules is either not correct, or not precise. You can't solve it with an AFTER trigger, because you can't attempt to insert a blank into a numeric field, nor can you with a BEFORE trigger. You can't use a default either.
Now, if you mean that "when left blank" means "when left null", then you can solve it with a very carefully crafted BEFORE TRIGGER. (Or an AFTER TRIGGER, if you can change the field to a nullable int)
If you mean that "when left blank" means that you don't mention the column in your insert/update, then you might be able to get by with a carefully crafted default, by converting a call to GUID via NewID to a very large number.
As a side note, I would tell the designer to go back and redesign it, because whatever solution you do finally come up with, it is not very scalable, and a PITA to do correctly. You have to basically lock the entire table (from reading and writing), do an entire table/index scan to make sure the value you come up with is UNIQUE. You probably should be using the ID field as the client no, possibly seeding the identity with something not starting with 0.

Execute a query to SET IDENTITY OFF first, insert, your ID, then SET IDENTITY ON again.

Related

Reuse deleted ID field in MSSQL

Suppose I've an ID column in database:
I want to delete row number 3:
Now Id's in my database are following:
Question: Is it possible to reuse (in this case) ID 3 field. So ID 4 jumps to ID 3 field? So database should be like that:
I also know about RESEED command DBCC CHECKIDENT (MyTable, RESEED, desiredIDNumber), but I don't think that I need this in my case. Becase ALL ID's from (in my case) 2> will change. (ID3 gets ID4, and ID4 gets ID5. ID5 does not exists anymore).
Are you asking if there is a magical command to do this? Not that I have ever heard of. {Frankly I have never heard anyone even want to do this before}
Are you asking if this is technically possible? Sure. It would be a major undertaking. You could write a program that does this but the overhead of all that work to change all of the foreign key references would be pretty massive which leads to ...
Why? What are you expecting to get out of this? "Empty" space does not hurt. Did you run out of space in the integer field?
The general idea would be: UPDATE T SET ID = ID - 1 WHERE ID > 3
You can customize this to your liking. Probably you need to enable identity insert for this statement.
Be careful because this might cause corruption if other data references these IDs. IDs are generally not supposed to change. Maybe you rather add a new column ContiguousID INT NOT NULL and let the IDENTITY value alone.
If the Id column is an identity column, you cannot get Sql Server to fill in the missing IDs as part of it's automatic increment process. It won't do it.
You can fill in the ID yourself, by using the SET IDENTITY_INSERT command.
Generally, it's not worth the trouble.

NHibernate - best strategy to map ID which isn't identity

Just a quick question, how would one map a primary key which must be assigned manually (data type int). So, there is no identity in the database, if code was manually written you would probably open a transaction, lock the table, take the highest id, increment by one, and insert the record with the new value.
Set the Id generator to be assigned. Find more info at http://barchitect.blogspot.com/2008/07/nhibernate-generator-and-primary-key.html
Actually, I used the increment generator, which somehow I've overlooked to exist. It has some constraints about its usage, but it suits the situation for now.

How to get the primary key from a table without making a second trip?

How would I get the primary key ID number from a Table without making a second trip to the database in LINQ To SQL?
Right now, I submit the data to a table, and make another trip to figure out what id was assigned to the new field (in an auto increment id field). I want to do this in LINQ To SQL and not in Raw SQL (I no longer use Raw SQL).
Also, second part of my question is: I am always careful to know the ID of a user that's online because I'd rather call their information in various tables using their ID as opposed to using a GUID or a username, which are all long strings. I do this because I think that SQL Server doing a numeric compare is much (?) more efficient than doing a username (string) or even a guid (very long string) compare. My questions is, am I more concerned than I should be? Is the difference worth always keeping the userid (int32) in say, session state?
#RedFilter provided some interesting/promising leads for the first question, because I am at this stage unable to try them, if anyone knows or can confirm these changes that he recommended in the comments section of his answer?
If you have a reference to the object, you can just use that reference and call the primary key after you call db.SubmitChanges(). The LINQ object will automatically update its (Identifier) primary key field to reflect the new one assigned to it via SQL Server.
Example (vb.net):
Dim db As New NorthwindDataContext
Dim prod As New Product
prod.ProductName = "cheese!"
db.Products.InsertOnSubmit(prod)
db.SubmitChanges()
MessageBox.Show(prod.ProductID)
You could probably include the above code in a function and return the ProductID (or equivalent primary key) and use it somewhere else.
EDIT: If you are not doing atomic updates, you could add each new product to a separate Collection and iterate through it after you call SubmitChanges. I wish LINQ provided a 'database sneak peek' like a dataset would.
Unless you are doing something out of the ordinary, you should not need to do anything extra to retrieve the primary key that is generated.
When you call SubmitChanges on your Linq-to-SQL datacontext, it automatically updates the primary key values for your objects.
Regarding your second question - there may be a small performance improvement by doing a scan on a numeric field as opposed to something like varchar() but you will see much better performance either way by ensuring that you have the correct columns in your database indexed. And, with SQL Server if you create a primary key using an identity column, it will by default have a clustered index over it.
Linq to SQL automatically sets the identity value of your class with the ID generated when you insert a new record. Just access the property. I don't know if it uses a separate query for this or not, having never used it, but it is not unusual for ORMs to require another query to get back the last inserted ID.
Two ways you can do this independent of Linq To SQL (that may work with it):
1) If you are using SQL Server 2005 or higher, you can use the OUTPUT clause:
Returns information from, or
expressions based on, each row
affected by an INSERT, UPDATE, or
DELETE statement. These results can be
returned to the processing application
for use in such things as confirmation
messages, archiving, and other such
application requirements.
Alternatively, results can be inserted
into a table or table variable.
2) Alternately, you can construct a batch INSERT statement like this:
insert into MyTable
(field1)
values
('xxx');
select scope_identity();
which works at least as far back as SQL Server 2000.
In T-SQL, you could use the OUTPUT clause, saying:
INSERT table (columns...)
OUTPUT inserted.ID
SELECT columns...
So if you can configure LINQ to use that construct for doing inserts, then you can probably get it back easily. But whether LINQ can get a value back from an insert, I'll let someone else answer that.
Calling a stored procedure from LINQ that returns the ID as an output parameter is probably the easiest approach.

Is the usage of identity insert good with metadatatables

I have several tables within my database that contains nothing but "metadata".
For example we have different grouptypes, contentItemTypes, languages, ect.
the problem is, if you use automatic numbering then it is possible that you create gaps.
The id's are used within our code so, the number is very important.
Now I wonder if it isn't better not to use autonumbering within these tables?
Now we have create the row in the database first, before we can write our code. And in my opinion this should not be the case.
What do you guys think?
I would use an identity column as you suggest to be your primary key(surrogate key) and then assign your you candidate key (identifier from your system) to be a standard column but apply a unique constraint to it. This way you can ensure you do not insert duplicate records.
Make sense?
if these are FK tables used just to expand codes into a description or contain other attributes, then I would NOT use an IDENTITY. Identity are good for ever inserting user data, metadata tables are usually static. When you deploy a update to your code, you don't want to be suprised and have an IDENTITY value different than you expect.
For example, you add a new value to the "Languages" table, you expect the ID will be 6, but for some reason (development is out of sync, another person has not implemented their next language type, etc) the next identity you get is different say 7. You then insert or convert a bunch of rows having using Language ID=6 which all fail becuase it does not exist (it is 7 iin the metadata table). Worse yet, they all actuall insert or update because the value 6 you thought was yours was already in the medadata table and you now have a mix of two items sharing the same 6 value, and your new 7 value is left unused.
I would pick the proper data type based on how many codes you need, how often you will need to look at it (CHARs are nice to look at for a few values, helps with memory).
for example, if you only have a few groups, and you'll often look at the raw data, then a char(1) may be good:
GroupTypes table
-----------------
GroupType char(1) --'M'=manufacturing, 'P'=purchasing, 'S'=sales
GroupTypeDescription varchar(100)
however, if there are many different values, then some form of an int (tinyint, smallint, int, bigint) may do it:
EmailTypes table
----------------
EmailType smallint --2 bytes, up to 32k different positive values
EmailTypeDescription varchar(100)
If the numbers are hardcoded in your code, don't use identity fields. Hardcode them in the database as well as they'll be less prone to changing because someone scripted a database badly.
I would use an identity column as the primary key also just for simplicity sake of inserting the records into the database, but then use a column for type of metadata, I call mine LookUpType(int), as well as columns for LookUpId (int value in code) or value in select lists, LookUpName(string), and if those values require additional settings so to speak use extra columns. I personally use two extras, LookUpKey for hierarchical relations, and LookUpValue for abbreviations or alternate values of LookUpName.
Well, if those numbers are important to you because they'll be in code, I would probably not use an IDENTITY.
Instead, just make sure you use a INT column and make it the primary key - in that case, you will have to provide the ID's yourself, and they'll have to be unique.

Do you need to specify all fields in an insert

When performing an insert lets say from C# into a SQL Server table (using parameterized sql statements), do you need to specify every table field in the insert statement?
I noticed that the fields that I do not specify in the insert default to the defaults set in the table. I don't know if that's good or bad in my insert statement to leave out fields and let the defaults take care of setting the fields I don't care about. It must be ok because it works.
You need to specify all those field for which you want to insert a value. You do not have to specify all fields in the table!
As you noticed, any of the fields that you do not specify and that do have a default constraint on them will be set to that defined default value. It's a "good thing" (tm) - for sure! This allows you to write less T-SQL insert code - all the defined defaults will be set already. I find this to be a great feature of SQL Server (and lots of other relational databases, too) - you can initialize things like "last modified" date fields to "today" upon insert without having to specifically add those fields to your INSERT statement.
Any fields that are neither part of your INSERT statement, nor have a default value defined, will be left NULL.
Any fields that are defined as NOT NULL must be either part of the list of fields in your INSERT statement (so that you give them a specific NON NULL value), or they have to have a default constraint on them.
This is not a behavior specific to C# or .NET.
With most databases, any fields that are omitted from an INSERT statement are assigned the default values, or if nullable are stored as NULL. This is standard, and expected behavior.
As for whether this is good or bad - it depends. Personally, I prefer to specify the values of all fields in any table I am inserting into so that future maintainers realize that I chose to insert the values by intent. However, in some cases, there are calculations or trigger-based columns which the application cannot set - in which case I allow the database to handle this.
If you really want to be thorough and clear - you can perform all of your INSERTs through stored procedures - this way the knowledge is captured in the database layer and can be leveraged by any applications that interact with the database.
Yes it is ok to leave out fields in an insert statement if the defaults are good enough for you.
Well seeing as it works, its ok if its what you want to achieve. If you have nullable fields and fields with default values, and nothing to put in them - well thats just fine.
This is what defaults values are there for. They help you to
save your time
avoid writing unnecessary code
It is fine if the default values are the values that are correct for the record you are inserting. What concerns me is that you talk about them as fields that you don't care about. You should care what goes into them; it can lead to serious data problems to not care. Those fields are there for a reason; you need to understand what the defaults mean and if they are appropriate.

Categories