I have a table in a database like this:
ID,Name,Val,Pos.
01,ValueN1,10,0
01,ValueN2,5,1
01,ValueN3,6,2
01,ValueN4,7,3
01,ValueN5,10,4
I need to add a value: 01, ValueN6, 10, 3
The column Pos is a key so I need to rewrite all the values (I suppose). The result I need is :
01,ValueN1,10,0
01,ValueN2,5,1
01,ValueN3,6,2
01,ValueN6,10,3
01,ValueN4,7,4
01,ValueN5,10,5
There is a way? If I simply add the value I get an error of duplication key because pos=3 already exist.
From the above discussion, it sounds like you have a UNIQUE constraint defined the Pos column. In that case, you should be able to adjust the other values to accommodate the insert as folows.
BEGIN TRANSACTION
UPDATE YourTable
SET Pos = Pos + 1
WHERE Pos >= 3
INSERT YourTable (ID, Name, Val, Pos)
VALUES ('01', 'ValueN6', 10, 3)
COMMIT
I presume the "3" and other values will be parameterized in your logic.
If in fact it is referenced as a foreign key from another table, you will need to first verify that the foreign key definition is defined with the ON UPDATE CASCADE option.
Side note: If your design uses the same column for both ordering and referential integrity, it may be time to rethink that design.
Related
I want to copy all columns from dbo.die to dbo.technology.
Both tables exist! In dbo.technology, the primary key is idTechnology
In dbo.die, the primary key is idDie and we have a foreign key, which is Technology_idTechnology in it, which connects the die table with the technology table.
How could I do that, so that the values got copied to the right rows, which match the same idTechnology?
I tried this:
INSERT INTO dbo.die
(Technology_idTechnology, Technology_D, Technology_Type, Technology_Manufacturer, Technology_SOI, Technology_Node, Technology_Name, Technology_Number_Metal, Technology_Number_Poly, Technology_Power_Cu, Technology_FEComplexity, Technology_FEComplexity_Sec, Technology_Trench, Technology_IMID, Technology_Remarks)
SELECT *
FROM dbo.technology tech
WHERE tech.idTechnology = idTechnology;
but I'm always getting an error!
Cannot insert duplicate key row in object 'dbo.die' with unique index 'ui_dieIdsample'. The duplicate key value is ().
Don't know what I should do.. I thought it's easy & simple
If a column is declared as NOT NULL (and has no default value), a value for the column must be specified in the INSERT statement.
In this specific case you should add Table2_Feld to the insert column list, and specify a value in the SELECT for it!
You will need to change your column list (lets say that its acceptable to insert a default value of 0 into column Table2_Feld)
INSERT INTO dbo.table2
(Table1_idTech, Tech_D, Techn_Type, Tech_Man,
Techn_Node, Tech_Name, Technology_Numb, Tech_Po,
Tech_FEC, Techn_Comp_Sec,
Tech_R,Table2_Feld)
select *,0 from table1 tech
In a database application, I want to insert, update and delete records in a table of database.
Table is as below:
In this table, Ga1_ID is Primary Key.
Suppose, I insert 5 records as show currently.
In second attempt, if I want to insert 5 other records and if any of these new records contains a primary key attribute which is already present in table it show error. Its fine.
But, when I insert new 5 records... how I can verify these new records's primary key value is not present. I mean, how to match or calculate the already present primary key attributes and then insert new records.
What is the best approach to manage this sort of situation ?
use following query in dataadapter:
da=new SqlDataAdapter("select Ga1_ID from table where Ga1_ID=#pkVal",conn);
DataSet=new DataSet();
da.fill(ds);
//pass parameter for #pkVal
da.SelectCommand.Parameters(1).Value = pkValue;
if(ds.Tables[0].Rows.Count>0) //If number of rows >0 then record exists
BEGIN
messagebox.show("Primary key present");
END
Hope its helpful.
Do not check existing records in advance, i.e. do not SELECT and then INSERT. A better (and pretty common) approach is to try to INSERT and handle exceptions, in particular, catch a primary key violation if any and handle it.
Do the insert in a try/catch block, with different handling in case of a primary key violation exception and other sql exception types.
If there was no exception, then job's done, record was inserted.
If you caught a primary key violation exception, then handle it appropriately (your post does not specify what you want to do in this case, and it's completely up to you)
If you want to perform 5 inserts at once and want to make sure they all succeed or else roll back if any of them failed, then do the inserts within a transaction.
you can do a lookup first before inserting.
IF EXISTS (SELECT * FROM tableName WHERE GA1_id=#newId)
BEGIN
UPDATE tableName SET Ga1_docid = #newdocID, GA1_fieldNAme = #newName, Ga1_fieldValue = #newVal where GA1_id=#newId
END
ELSE
BEGIN
INSERT INTO tableName(GA1_ID, Ga1_docid, GA1_fieldNAme Ga1_fieldValue) VALUES (value1,val2,value3,value4)
END
If you're using SQL Server 2012, use a sequence object - CREATE SEQUENCE.
This way you can get the next value using NEXT VALUE FOR.
With an older SQL Server version, you need to create the primary key field as an IDENTITY field and use the SCOPE_IDENTITY function to get the last identity value and then increment it manually.
Normally, you would like to have a surrogate key wich is generally an identity column that will automatically increment when you are inserting rows so that you don't have to care about knowing which id already exists.
However, if you have to manually insert the id there's a few alternatives for that and knowing wich SQL database you are using would help, but in most SQL implementations, you should be able to do something like:
IF NOT EXISTS
IF NOT EXISTS(
SELECT 1
FROM your_table
WHERE Ga1_ID = 1
)
INSERT INTO ...
SELECT WHERE NOT EXISTS
INSERT INTO your_table (col_1, col_2)
SELECT col_1, col_2
FROM (
SELECT 1 AS col_1, 2 AS col_2
UNION ALL
SELECT 3, 4
) q
WHERE NOT EXISTS (
SELECT 1
FROM your_table
WHERE col_1 = q.col_1
)
For MS SQL Server, you can also look at the MERGE statement and for MySQL, you can use the INSERT IGNORE statement.
I've declared the following table for use by audit triggers:
CREATE TABLE audit_transaction_ids (id IDENTITY PRIMARY KEY, uuid VARCHAR UNIQUE NOT NULL, `time` TIMESTAMP NOT NULL);
The trigger will get invoked multiple times in the same transaction.
The first time the trigger is invoked, I want it to insert a new
row with the current TRANSACTION_ID() and time.
The subsequent times the trigger is invoked, I want it to return
the existing "id" (I invoke Statement.getGeneratedKeys() to that end)
without altering "uuid" or "time".
The current schema seems to have two problems.
When I invoke MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES(TRANSACTION_ID(), NOW()) I get: org.h2.jdbc.JdbcSQLException: Column "ID" contains null values; SQL
statement: MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES
(TRANSACTION_ID(), NOW()) [90081-155]
I suspect that invoking MERGE on an existing row will alter "time".
How do I fix both these problems?
MERGE is analogous to java.util.Map.put(key, value): it will insert the row if it doesn't exist, and update the row if it does. That being said, you can still merge into a table containing AUTO_INCREMENT columns so long as you use another column as the key.
Given customer[id identity, email varchar(30), count int] you could merge into customer(id, email, count) key(email) values((select max(id) from customer c2 where c2.email='test#acme.com'), 'test#acme.com', 10). Meaning, re-use the id if a record exists, use null otherwise.
See also https://stackoverflow.com/a/18819879/14731 for a portable way to insert-or-update depending on whether a row already exists.
1. MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES(TRANSACTION_ID(), NOW())
If you just want to insert a new row, use:
INSERT INTO audit_transaction_ids (uuid, time) VALUES(TRANSACTION_ID(), NOW())
MERGE without setting the value for the column ID doesn't make sense if ID is used as the key, because that way it could never (even in theory) update an existing rows. What you could do is using another key column (in the case above there is no column that could be used). See the documentation for MERGE for details.
2. Invoking MERGE on an existing row will alter "time"
I'm not sure if you talk about the fact that the value of the column 'time' is altered. This is the expected behavior if you use MERGE ... VALUES(.., NOW()), because the MERGE statement is supposed to update that column.
Or maybe you mean that older versions of H2 returned different values within the same transaction (unlike most other databases, which return the same value within the same transaction). This is true, however with H2 version 1.3.155 (2011-05-27) and later, this incompatibility is fixed. See also the change log: "CURRENT_TIMESTAMP() and so on now return the same value within a transaction." It looks like this is not the problem in your case, because you do seem to use version 1.3.155 (the error message [90081-155] includes the build / version number).
Short Answer:
MERGE INTO AUDIT_TRANSACTION_IDS (uuid, time) KEY (uuid, time)
VALUES (TRANSACTION_ID(), NOW());
little performance tip: make sure uuid is indexed
Long Answer:
MERGE is basically an UPDATE which INSERTs when no record found to be updated.
Wikipedia gives a more concise, standardized syntax of
MERGE but you have to supply your own update and insert.
(Whether this will be supported in H2 or not is not mine to answer)
So how do you update a record using MERGE in H2? You define a key to be looked up for, if it is found you update the row (with column names you supply, and you can define DEFAULT here, to reset your columns to its defaults), otherwise you insert the row.
Now what is Null? Null means unknown, not found, undefined, anything which is not what you're looking for.
That is why Null works as key to be looked up for. Because it means the record is not found.
MERGE INTO table1 (id, col1, col2)
KEY(id) VALUES (Null, 1, 2)
Null has a value. it IS a value.
Now let's see your SQL.
MERGE INTO table1 (id, col1, col2)
KEY(id) VALUES (DEFAULT, 1, 2)
What is that implying? To me, it says
I have this [DEFAULT, 1, 2], find me a DEFAULT in column id,
then update col1 to 1, col2 to 2, if found.
otherwise, insert default to id, 1 to col1, 2 to col2.
See what I emphasized there? What does that even mean? What is DEFAULT? How do you compare DEFAULT to id?
DEFAULT is just a keyword.
You can do stuff like,
MERGE INTO table1 (id, col1,
timeStampCol) KEY(id) VALUES (Null, 1,
DEFAULT)
but don't put DEFAULT in the key column.
There is a need to build constraint on the column that guarantees that only one value in all rows is 1 and all the others are 0.
Solution with triggers exists but I would like to have something built in.
Is such thing possible at all?
Edit
Actually I just noticed you are on SQL Server 2008 you could use a filtered index for this
CREATE UNIQUE NONCLUSTERED INDEX UIX ON YourTable (col) where col = 1
Original Answer
The easiest way would probably be to store this one special pk in a separate one row table. The no more than one row aspect can be enforced with check constraints.
CREATE TABLE OneRowTable
(
lock CHAR(1) DEFAULT 'X' NOT NULL PRIMARY KEY CHECK (lock = 'X'),
OtherTablePK int
);
Otherwise assuming you might have an id field comprised of positive integers you could add a computed column with the following definition
case when col=1 then -1 else id end
and add a unique constraint to that.
I have an sql table which is basically a statement.
Now lets say the records I have in my table have a date and an identity column which is autonumbered and defines the order which the transactions are displayed in the front end to the client.
The issue is during an insert some of the data have gone missing and some transactions between two dates are missing.
I need to insert the data into the table, but I need to insert them between the dates and not at the end of the table. If I do a a normal insert, the data will appear at the end of the table and not at the date I specify, because the identity column is autonumbered, and cannot be updated.
Using SET IDENTITY_INSERT (table) ON, you force SQL Server to let you insert any arbitrary value into an IDENTITY column - but there's no way to update an IDENTITY column.
What's the big problem with a few gaps anyway?? Yes, it might be a bit of a "cosmetic" problem - but how much hassle and effort do you really want to spend on cosmetic problems?? The order of the entries is still a given - even with gaps.
So again: what's the big deal?? IDENTITY columns are guaranteed to be ever increasing - that's all they guarantee. And for 99% of the cases, that's more than good enough....
Why not just display the records in the user interface sorted by the date, rather than by the primary key?
OK, if you really want to do this (personally, I think changing the sort date in the UI is going to be easier than updating the primary key values in the database, but anyway...). This should work, assuming you're not using the primary key values in any foreign key constraints (if you are, then you'll need to make sure those constraints have ON UPDATE CASCADE set)
SET IDENTITY_INSERT tablename ON
UPDATE tablename SET
primary_key = primay_key + 1
WHERE
primary_key >= <the primary key where you want to insert the new date>
INSERT INTO tablename
(primary_key, date, ...)
VALUES
(<the primary key to insert>, <the date to insert>, ...)
SET IDENTITY_INSERT tablename OFF
However, I strongly, strongly suggest you backup your database before attempting this.
Just out of curiosity, is it one ID per date? Your answers imply this a little, so if so, replace the Identity column with a computed column that is defined as the date difference in days from an arbitrary starting point?
DECLARE #EXAMPLE TABLE
(
[Date] DATE,
ID AS DATEDIFF(Day, '1 Jan 2010', [Date])
)
INSERT INTO #EXAMPLE([Date])
VALUES (GETDATE()), (GETDATE()+1), (GETDATE()+2)
SELECT * FROM #EXAMPLE