problem in inserting data into table in 24-073110-XX format ???? - c#

I need help insering an id into the database in ASP.net mvc (C#). Here theid is the primary key and it should be in the format 24-073110-XX, where XX represents a numeric value which should be incremented by 1.
How should I insert the id in this format?

As Rob said - don't store the whole big identifier in your table - just store the part that changes - the consecutive number.
If you really need that whole identifier in your table, e.g. for displaying it, you could use a computed column:
ALTER TABLE dbo.MyTable
ADD DisplayID AS '24-073110-' + RIGHT('00' + CAST(ID AS VARCHAR(2)), 2) PERSISTED
This way, your INT IDENTITY will be used as an INT and always contains the numerical value, and it will be automatically incremented by SQL Server.
Your DisplayID field will then contain values like:
ID DisplayID
1 24-073110-01
2 24-073110-02
12 24-073110-12
13 24-073110-03
21 24-073110-21
Since it's a persisted field, it's now part of your table, and you can query on it, and even put an index on it to make queries faster:
SELECT (fields) FROM dbo.MyTable WHERE DisplayID = '24-073110-59'
Update:
I would definitely not use DisplayID as your primary key - that's what the ID IDENTITY column is great for
to create an index on DisplayID is no different than creating an index on any other column in your table, really:
CREATE NONCLUSTERED INDEX SomeIndex ON dbo.MyTable(DisplayID)

If the 24-073110- part of the data is always going to be the same, there's little to no point in storing it in the database. Given that you've said that the XX component is a numeric value that increments by one, I'd suggest having your table created similarly to this:
CREATE TABLE [dbo].[MyTable]
(
MyTableId INT IDENTITY(1,1) NOT NULL,
/*
Other columns go here
*/
)
This way, you can let the database worry about inserting unique automatically incrementing values for your primary key.

Related

SqLite Auto-increment for one its Composite Keys

The following columns are set to auto-increment in SQL Server IDENTITY(1,1) and I wanted similar behavior on SqLite: Tenant.TenantID, Project.ProjectID, and Credits.CreditsID. Although there is AUTOINCREMENT in SqLite, and I have tried it, but it only works on tables with only 1 Primary Key. I have tried the following testing:
By the way, I used Microsoft.EntityFrameworkCore.Sqlite 2.1.4 for this testing
Explicitly assign value for these columns set to auto-increment:
Tenant.TenantID
a. -99 : remains -99 after saving
b. 0 : becomes 1 after saving
c. 99 : remains 99 after saving
For Project.ProjectID & Credits.CreditsID
a. -99 & 99 values remains the same after saving changes to DbContext. But I do not want to explicitly assign these values because there are bunch of test data from my DbContext.
b. Assigning explicit value 0 throws this error: Microsoft.Data.Sqlite.SqliteException : SQLite Error 19: 'NOT NULL constraint failed: Credits.CreditsID'.
I'd really be grateful for someone who can help me out with this one. It's been days that this bothers me.
With SQLite you probably do not want to use AUTOINCREMENT, this does not actually set the column to increment rather it sets a constraint that the value, if not set explicitly must be a higher value than has been allocated.
Simply defining a column using INTEGER PRIMARY KEY sets the column to increment if not explicitly setting the value. Noting that there can only be one such column per table.
Note that SQLite DOES NOT guarantee incrementing by 1 rather it guarantees a unique identifier which is an integer and may even be less (only after and id of 9223372036854775807 has been assigned).SQLite Autoincrement. In which case using AUTOINCREMENT will fail with an SQLIte Full exception, whilst without AUTOINCREMENT SQLite will try to find an unused id.
Looking at your diagram I believe the the Credits table would not need the TennantID as this is available via the Project referencing the Tennant.
Ignoring other than the columns that make up the relationships (also adding the optional foreign key restraints that would enforce referential integrity) then I believe you could use something along the lines of :-
DROP TABLE IF EXISTS credits;
DROP TABLE IF EXISTS project;
DROP TABLE IF EXISTS tennant;
CREATE TABLE IF NOT EXISTS tennant (tennant_id INTEGER PRIMARY KEY, Name TEXT, other_columns);
CREATE TABLE IF NOT EXISTS project (project_id INTEGER PRIMARY KEY, tennant_reference REFERENCES tennant(tennant_id), Title);
CREATE TABLE IF NOT EXISTS credits (credit_id INTEGER PRIMARY KEY, project_reference INTEGER REFERENCES project(project_id), other_columns TEXT);
CREATE TABLE IF NOT EXISTS creidts (credit_id INTEGER PRIMARY KEY, project_reference INTEGER, other_columns);
INSERT INTO tennant VALUES(1,'Fred','other data'); -- Explicit ID 1
INSERT INTO tennant (Name,other_columns) VALUES('Mary','Mary''s other data'),('Anne','Anne''s other data'); -- Implicit ID 's (2 and 3 most likely)
INSERT INTO project VALUES (99,1,'Project001 for Fred'); -- Explicit Project ID 99 - tennant 1 = Fred
INSERT INTO project (tennant_reference,Title) VALUES(1,'Project002 for Fred'),(2,'Project003 for Mary'),(3,'Project004 for Anne'); -- 3 implicit project id's 100,101 and 102 (most likely)
-- Result 1
SELECT * FROM project JOIN tennant ON tennant_reference = tennant.tennant_id;
INSERT INTO credits VALUES(199,99,'Other credit columns'); -- Explicit credit ID of 199 for Project001 (tennant implied)
INSERT INTO credits VALUES(0,99,'Other credit colums credit_id = 0'); -- Explicit credit ID of 0 for Project002
INSERT INTO credits (project_reference,other_columns) VALUES (100,'for Project002'),(100,'another for Project002'),(102,'for Project004');
SELECT * FROM credits JOIN project ON project_reference = project_id JOIN tennant ON tennant_reference = tennant_id;
This drops all the existing tables to make testing simpler.
The 3 tables are then created.
Rows are inserted both explicitly and implicitly (the recommended way) into the Tennant table and then into the Project table (note that rows that reference a non-existent tennant cannot be inserted into the Project table due to the foreign key constraint)
The Projects, along with the joined tennant details are then listed (see Results)
Rows are then inserted into the Credits table using Explicit and Implicit credit id's (note that 199 is Explicitly defined and then 0).
As you can see when id's are autogenerated they generally are 1 greater than the greatest value used to date.
Results
First query (Project's with related Tennant)
Second Query Credits with related Project and the underlying related Tennant

How to reorder auto increment column values, after deleting any row other than last row?

I want to know is there any SQL query for asp.net,c# that can just re arrange auto increment coloumn values..
eg.
deleting 2 in the table:
sno
1
2
3
4
does:
sno
1
3
4
but i want re-arrangement:
sno
1
2
3
Note:
Don't want to to the numbering manually
query to create table is like this:
CREATE TABLE uid (sno int IDENTITY(1,1) PRIMARY KEY, qpname nvarchar(500), mob int, tm int)
Let your table be named Parent and table that will hold the backup is called Backup. They should have identical columns.
INSERT INTO dbo.Backup
SELECT * FROM dbo.Parent
Now truncate the parent table
TRUNCATE TABLE dbo.Parent
Now you can just insert the data back using the first command and just reversing the table names.
Remember that this may not work in all cases. You may have On delete cascade on and if that is the case, then you would loose all data from other tables also which are referencing the parent table. I think that you should never use this is you are using any Foriegn Key reference on this table.
Following are the queries which should run 1 after other to get this functionality done. This can be easily achieved in C# by executing a generic ExecuteNonQuery().
DELETE FROM TBL1 WHERE sno = #sno;
UPDATE TBL1
SET sno = sno -1
WHERE sno > #sno;

reset rowid in sqlite after deleting a row

When I delete a row from my table, the rowID number is deleted; this means that the rowIDs are not truly sorted any more.
In this case, I want to reset the rowID such that the new IDs will be sorted and consecutive.
I tried to do this with ALTER TABLE :
ALTER TABLE my_table DROP ID;
ALTER TABLE my_table AUTO_INCREMENT = 1;
ALTER TABLE my_table ADD ID int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;
... but this doesn't work. How can I get the consecutive numbers?
It is technically possible, if somewhat inadvisable - Set start value for AUTOINCREMENT in SQLite . But it sounds like you are using autoincrement wrong, you definitely should not have to change id values of every row each time a row is deleted from the table. This makes joining other tables in a query very difficult for one thing, and will be horrendously slow on a large table. Why does it matter if the id are 1,2,4 and not 1,2,3 anyway ? You can still ORDER BY them the same way.

SQL Server - formatted identity column

I would like to have a primary key column in a table that is formatted as FOO-BAR-[identity number], for example:
FOO-BAR-1
FOO-BAR-2
FOO-BAR-3
FOO-BAR-4
FOO-BAR-5
Can SQL Server do this? Or do I have to use C# to manage the sequence? If that's the case, how can I get the next [identity number] part using EntityFramwork?
Thanks
EDIT:
I needed to do this is because this column represents a unique identifier of a notice send out to customers.
FOO will be a constant string
BAR will be different depending on the type of the notice (either Detection, Warning or Enforcement)
So is it better to have just an int identity column and append the values in Business Logic Layer in C#?
If you want this 'composited' field in your reports, I propose you to:
Use INT IDENTITY field as PK in table
Create view for this table. In this view you can additionally generate the field that you want using your strings and types.
Use this view in your repoorts.
But I still think, that there is BIG problem with DB design. I hope you'll try to redesign using normalization.
You can set anything as the PK in a table. But in this instance I would set IDENTITY to just an auto-incrementing int and manually be appending FOO-BAR- to it in the SQL, BLL, or UI depending on why it's being used. If there is a business reason for FOO and BAR then you should also set these as values in your DB row. You can then create a key in the DB between the two three columns depending on why your actually using the values.
But IMO I really don't think there is ever a real reason to concatenate an ID in such a fashion and store it as such in the DB. But then again I really only use an int as my ID's.
Another option would be to use what an old team I used to be on called a codes and value table. We didn't use it for precisely this (we used it in lieu of auto-incrementing identities to prevent environment mismatches for some key tables), but what you could do is this:
Create a table that has a row for each of your categories. Two (or more) columns in the row - minimum of category name and next number.
When you insert a record in the other table, you'll run a stored proc to get the next available identity number for that category, increment the number in the codes and values table by 1, and concatenate the category and number together for your insert.
However, if you're main table is a high-volume table with lots of inserts, it's possible you could wind up with stuff out of sequence.
In any event, even if it's not high volume, I think you'd be better off to reexamine why you want to do this, and see if there's another, better way to do it (such as having the business layer or UI do it, as others have suggested).
It is quite possible by using computed column like this:
CREATE TABLE #test (
id INT IDENTITY UNIQUE CLUSTERED,
pk AS CONCAT('FOO-BAR-', id) PERSISTED PRIMARY KEY NONCLUSTERED,
name NVARCHAR(20)
)
INSERT INTO #test (name) VALUES (N'one'), (N'two'), (N'three')
SELECT id, pk, name FROM #test
DROP TABLE #test
Note that pk is set to NONCLUSTERED on purpose because it is of VARCHAR type, while the IDENTITY field, which will be unique anyway, is set to UNIQUE CLUSTERED.

Violation of PRIMARY KEY constraint Cannot insert duplicate key in object . In C#.net....Visual Studio 2010...framework 3.5

I'm Developing a small windows application in C#.net in Visual Studio 2010 with framework 3.5. I use LinqToSql for database manipulation.
table name: cprofile
Fields of the table are:
custid int (primary key),
custname varchar(50),
address nvarchar(MAX),
mobileno nchar(10)
So i have changed the 'Is identity' property of the 'cust id' to 'yes'. It automatically changes other 2 sub properties.
Identity Increment = 1
Identity Seed = 1,
After these changes have been made in the table, it throws error when I try to save a new record.
"Cannot insert explicit value for identity column in table 'cprofile'
when IDENTITY_INSERT is set to OFF."
Not too familiar with L2S, but I'd say Daniel is correct: update your model (usually on a context menu somewhere) from the DB. That should prevent it from attempting to insert a value into your auto-incrementing ID column.
I believe there may be a way to have it set IDENTIY_INSERT ON, but I highly recommend against it.
If your table should not be in charge of setting the CustomerId (say, the business has some method of making that determination (especially in a non-linear way), leave your Customer Id column as the PK, but remove the Identity specificaiton from the column.
If you're trying to use the same insert statement you were using before, you can no longer do that. I'm not sure how it's done in the C# side of it, but in SQL, you'd have to run statements to turn identity_insert on, then run your statement. Because you changed the column to identity, the table makes sure the next entry is always 1 number higher than the previous. Because of this, you can't simply insert values into it. If you want the table to create the identity value for you, simply remove it. If my explanation doesn't help, hopefully this will.
Table Definition (Table1)
Col1 Identity
Col2 varchar(50)
Col3 bool
Insert statement before identity
INSERT INTO Table1 VALUES (1, 'Test', TRUE)
Insert statement after identity
INSERT INTO Table1 VALUES ('Test', TRUE)
When identity is on, you cannot specify the value without turning on identity_edit. I'll see if I can find how to do that in Linq.
EDIT: I also like what Daniel said. Didn't think about that.

Categories

Resources