Related
In a PostgreSQL DB table, I need to copy a block of records from a prior month, change values in some of the columns, and append the updated records to the table. Details include:
The key id is configured with nextval to automatically create
unique key values
The target records have '200814' in group_tag
The new records need '200911' in group_tag
Several other fields need to be updated as shown in the SELECT
My script so far:
INSERT INTO hist.group_control(
id,
group_tag,
process_sequence,
state,
cbsa_code,
window_starts_on,
preceding_group,
preceding_origin,
preceding_window_starts_on
)
SELECT id,
'200911',
1,
state,
cbsa_code,
'2020-09-11',
'200814',
preceding_origin,
'2020-08-14'
FROM hist.group_control WHERE group_tag='200814';
This generates an error:
SQL Error [23505]: ERROR: duplicate key value violates unique constraint "group_control_pkey"
Detail: Key (id)=(12250) already exists.
Records with key values up to 13008 exist. I would have expected nextval to determine this and start the id value at 13009. I attempted to simply not include id in the statement thinking the nextval function would operate automatically, but that errored as well. Variations on the following have not worked due to the respective errors:
alter sequence group_control_id_seq restart with 13009;
SQL Error [42501]: ERROR: must be owner of relation group_control_id_seq
SELECT setval('group_control_id_seq', 13009, true);
SQL Error [42501]: ERROR: permission denied for sequence group_control_id_seq
Anyone know how to code the main statement to not generate the duplicate key or alternatively, how to tell nextval to start at a value of 13009
It appears your serial, bigserial, or generated by default. Any of these only assign the id column when it is not specified in the insert statement. If you specify the id column Postgres will not assign a key PK. Since you selected the id, Postgres attempted to use what you specified. Solution drop id from the insert statement.
INSERT INTO hist.group_control(
group_tag,
process_sequence,
state,
cbsa_code,
window_starts_on,
preceding_group,
preceding_origin,
preceding_window_starts_on
)
SELECT '200911',
1,
state,
cbsa_code,
'2020-09-11',
'200814',
preceding_origin,
'2020-08-14'
FROM hist.group_control WHERE group_tag='200814';
After no row deletion, but after getting the 60 existing rows by local subscription to replication from another SQL Server instance, I'm inserting new rows with:
INSERT INTO [Business].[dbo].[ImagesTable] (Filename, Title, Price, PriceString, Category, CategoryRank)
VALUES ('vegan1.jpg', 'vegan1', 380000, '380,000', 'delices vegan', 0)
But this will fail since the ID will start over somewhere (9 in this case), instead of starting at the last ID used +1, ie., 61 in my case.
System.Data.SqlClient.SqlException: 'Violation of PRIMARY KEY constraint 'PK_ImagesTable'. Cannot insert duplicate key in object 'dbo.ImagesTable'. The duplicate key value is (9).
My table is set to have autoincrement, therefore I should not have to use explicit IDENT_CURRENT('ImagesTable'). Why is this happening ?
Furthermore and despite this, when I try to insert explicitly ID I have:
Cannot insert explicit value for identity column in table 'ImagesTable' when IDENTITY_INSERT is set to OFF.
What is the recommended way to add new rows? How can I insert new rows with the ID being automatically set?
If the presence of DB replication is not propagating the Identity seed, how should I deal with this so I don't have to manage duplicate key errors (I'm certain that I'm not inserting duplicates)?
You need to segment your IDENTITY column ranges in bidirectional replication.
https://learn.microsoft.com/en-us/sql/relational-databases/replication/publish/replicate-identity-columns?view=sql-server-ver15
The primary key of my table is an Identity column of an ID. I want to be able to insert a new row and have it know what the last ID in the table currently is and add one to it. I know I can use Scope Identity to get the last inserted column from my code, but I am worried about people manually adding entries in the database, because they do this quite often. Is there a way I can look at the last ID in the table and not just the last ID my code inserted?
With a SQL Identity column, you don't need to do anything special. This is the default behavior. SQL Server will handle making sure you don't have collisions regardless of where the inserts come from.
The ##Identity will pull the latest identity, and scope_identity will grab the identity from the current scope.
A scope is a module: a stored procedure, trigger, function, or batch. Therefore, if two statements are in the same stored procedure, function, or batch, they are in the same scope.
If you don't want to allow manual entries to the primary column, then you can add Identity constraint to it along with primary key constraint.
Example, while creating a table,
CREATE Table t_Temp(RowID Int Primary Key Identity(1,1), Name Varchar(50))
INSERT Into t_Temp values ('UserName')
INSERT Into t_Temp values ('UserName1')
SELECT * from t_Temp
You can query the table and get the next available code in one SQL query:
SELECT COALESCE(MAX(CAST("RowID" AS INT)),0) +1 as 'NextRowID' from <tableName>
The "0" here is a default, meaning if there are no rows found, the first code returned would be (0+1) =1
Generally I have 999 instead of the 0 as I like my RowID/primary key etc. to start at 1000.
I'm running a data stage job, Input through DB2 and output to DB2. Input side has a query containing joins and functions.
I'm getting the following warning message;
TRN_HEALTH_INSURANCE_DETAIL,
2: STATEMENT
INSERT
INTO
HEALTH_INSURANCE_DETAIL
(
RISK_DETAIL_ID,
RISK_COVER_ID,
RD_POLICY_SYSTEM_NO,
RD_POLICY_END_NO_IDX,
RD_POLICY_ID,
RD_LEVEL1_ID,
RD_SUM_INSURED_AMT_LC,
RD_PREMIUM_AMT_LC,
PREMIUM_AMOUNT_FC,
SUM_INSURED_AMT_FC,
RD_REC_TYPE,
RD_EFFECT_FROM_DT,
RD_EFFECT_TO_DT,
RD_END_EFFECT_FROM_DT,
SEX_MAS_CD,
MARITAL_STATUS_CD,
EMP_CATG,
NO_OF_DEPENDENTS,
EMP_AL_NO,
DOB,
EFF_DATE,
EFF_DATE2,
NAME,
RELATIONSHIP_CD_S,
RELATIONSHIP_CD,
DESIGNATION,
BRANCH,
BANK_ACCOUNT,
BANK_BRANCH_NAME,
PRE_EXISTING_AILMENT,
AUTHORITY_LETTER_NO,
AGE,
REGION,
CNIC,
CO_CODE,
EMP_LOCATION,
SUB_LOCATION,
CLH_SYSTEM_NO,
CTH_SYS_ID,
CTH_POL_SYS_ID,
CTH_END_NO_IDX,
CTH_END_SR_NO,
CTH_CATEGORY,
CLD_SYS_ID,
CLDH_SYS_ID,
CLD_COVER_CD,
CLD_END_IDX,
CLD_COVER_DESC,
CLD_CLM_TYPE_LIMIT,
CLD_CLM_REL,
CLD_CLM_AGE_FROM,
CLD_CLM_AGE_TO,
CLD_CLM_RB_LIMIT,
CLD_CATEGORY_LIMIT_FC,
CLD_CATEGORY_PREM_FC
)
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) failed to run.
I cant see such records in my data. The data quality is good. Then what are these ????, I search a bit and found a suggestion to keep the array size and row count to 1, instead of default 2000. But still I'm getting the same warning.
There are a lot of errors followed by this warning; The next error is also interesting.
TRN_HEALTH_INSURANCE_DETAIL,2: SQLExecute reported: SQLSTATE = 23505: Native Error Code = -803: Msg = [IBM][CLI Driver][DB2/NT64] SQL0803N One or more values in the INSERT statement, UPDATE statement, or foreign key update caused by a DELETE statement are not valid because the primary key, unique constraint or unique index identified by "1" constrains table "DB2ADMIN.HEALTH_INSURANCE_DETAIL" from having duplicate values for the index key. SQLSTATE=23505 (CC_DB2DBStatement::executeInsert, file CC_DB2DBStatement.cpp, line 1,095)
I believe the errors are due to the first warning. Kindly help me out.
Regards, Nuh
Make a copy stage before the DB2 connector and put one link to the DB2 and the other to a dataset file to see the data in a data set. But the problem seems to be in the primary key you have a duplicate primary index or a duplicate unique index. It can be either in your data that you want to insert or maybe the table already have a record that you want to insert again
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.