Ok so I have 2 new tables: Client and Contract. I'm gonna focus on the first one as they have the same structure. Client looks like:
+-----------+---------+
| client_id | name |
+-----------+---------+
| Value 1 | Value 2 |
+-----------+---------+
And created like this:
CREATE TABLE Client (
client_id varchar2(15) NOT NULL,
name varchar2(100) NOT NULL,
CONSTRAINT Client_pk PRIMARY KEY (client_id)
) ;
Also I have an old table: old_contracts looking like:
+------------+----------+------+
| contractid | clientid | name |
+------------+----------+------+
| con1 | cli1 | n1 |
| con2 | cli2 | n2 |
| con3 | cli2 | n2 |
| con4 | cli3 | n3 |
| con5 | cli3 | n3 |
+------------+----------+------+
Defined:
CREATE TABLE old_contracts(
contractid varchar2(15) NOT NULL
clientid varchar2(15) NOT NULL,
name varchar2(100) NOT NULL
) ;
I want to take the data from old_contract and insert it into Client.
This old_contracts table has rows with duplicate clientid (one client can have more than one contract) but I don't want to have duplicates on Client table so I am doing this:
INSERT INTO Client (
client_id,
name
) SELECT DISTINCT
clientid,
name
FROM old_contracts;
to not get duplicates. Anyway, I'm getting this error:
Error SQL: ORA-00001: unique constraint (USER.CLIENT_PK) violated
00001.00000 - "unique constraint (%s.%s) violated"
What's going on? I believe the DISTINCT keyword was going to do the thing.
I've also tried adding a WHERE NOT EXISTS clause as suggested in related posts (i.e. this one), but the result I'm getting is the same error.
Most likely, the name is not always the same for a given clientid.
Try this instead:
INSERT INTO Client (
client_id,
name
) SELECT clientid,
max(name)
FROM old_contracts
GROUP BY clientid;
Related
How is the table made?
create table market_post
(
.
.
.
d_id varchar(20) constraint unique_d_id unique,
.
.
.
);
create index market_post_d_i_219a22_idx on market_post (d_id, is_deleted);
It should be noted that above code is DDL of table and i created the indexes and unique constraint when the table was created and was full of data (ALTER....)
Sometimes it allows duplicate value in d_id and sometimes it not allows!!
Let's test:
TEST1
SELECT id,d_id
FROM public.market_post
WHERE id in (1910764,2584556)
Result:
--------------------------------
| id | d_id |is_deleted|
--------------------------------
|1910764 | QYynk1fG | true |
--------------------------------
|2584556 | gYkgfj_M | true |
--------------------------------
now i want update:
UPDATE public.market_post SET d_id = 'gYkgfj_M'WHERE id = 1910764
Result:
[2022-07-24 10:31:52] 1 row affected in 116 ms
OMG! now result is:
---------------------
| id | d_id |
---------------------
|1910764 | gYkgfj_M |
---------------------
|2584556 | gYkgfj_M |
---------------------
interesting point
SELECT id,d_id FROM public.market_post WHERE d_id='gYkgfj_M'
only returnt one row !!!!!!!!
---------------------
| id | d_id |
---------------------
|1910764 | gYkgfj_M |
---------------------
TEST2
SELECT id,d_id
FROM public.market_post
WHERE id in (191076 , 258455)
Result:
--------------------------------
| id | d_id |is_deleted|
--------------------------------
|191076 | SYyFk1fA | false |
--------------------------------
|258455 | fYkDfjbb | false |
--------------------------------
now i want update:
UPDATE public.market_post SET d_id = 'fYkDfjbb' WHERE id = 191076
Result:
[23505] ERROR: duplicate key value violates unique constraint "unique_d_id"
Detail: Key (d_id)=(fYkDfjbb) already exists.
its guarantees that the duplicate value was not found in the rows where is_deleted=false
Unique constraint does not work in Postgres?(Of course it should work) Or has the index affected it?
is this bug? no , i tested it in new table (in my server and in SQL fiddle) and all of them work truly , and there isn't any bug
But the old table is not work
It should be noted that I created the indexes and unique constraint when the table was full of data
VAERSION:12
As #ErwinBrandstetter said in the comments, I should have rebuilt the indexes! Apparently, I had fallen into a Postgres bug
After running REINDEX TABLE market_post; everything was solved
The hard part was where I had to distinguish values with duplicate IDs and delete one of them! As I said in the question, Postgres returns only one of the records. I took the entire table with the help of pandas and identified the duplicate values and then removed them
After the steps, it was time to REINDEX
I'm using MariaDB 10.3. Is there a way to delete history for a specific record? I have a situation where once I delete a record, I'm under contract to remove all records (including historical ones).
Consider the following table:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`email` varchar(255) DEFAULT NULL,
`start_trxid` bigint(20) unsigned GENERATED ALWAYS AS ROW START,
`end_trxid` bigint(20) unsigned GENERATED ALWAYS AS ROW END,
PRIMARY KEY (`id`,`end_trxid`),
PERIOD FOR SYSTEM_TIME (`start_trxid`, `end_trxid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
And consider the following commands run against that table:
insert into users (name, email) values ('cory', 'name#corycollier.com'), ('bob', 'bob#gmail.com');
UPDATE users set name='Cory' where id=1;
UPDATE users set name='Cory Collier' where id=1;
UPDATE users set name='Cory C' where id=1;
UPDATE users set name='Cory' where id=1;
That leaves me with the following history:
select * from (select * from users FOR SYSTEM_TIME BETWEEN (NOW() - INTERVAL 1 DAY) and (NOW())) as history where id=1;
+----+--------------+-----------------------------+-------------+----------------------+
| id | name | email | start_trxid | end_trxid |
+----+--------------+-----------------------------+-------------+----------------------+
| 1 | cory | corycollier#corycollier.com | 697377 | 697384 |
| 1 | Cory Collier | corycollier#corycollier.com | 697384 | 697391 |
| 1 | Cory C | corycollier#corycollier.com | 697391 | 697394 |
| 1 | Cory | corycollier#corycollier.com | 697394 | 697401 |
I don't have a way to delete history for that user. I'd like to.
I have this table called InspectionsReview:
CREATE TABLE InspectionsReview
(
ID int NOT NULL AUTO_INCREMENT,
InspectionItemId int,
SiteId int,
ObjectId int,
DateReview DATETIME,
PRIMARY KEY (ID)
);
Here how the table looks:
+----+------------------+--------+-----------+--------------+
| ID | InspectionItemId | SiteId | ObjectId | DateReview |
+----+------------------+--------+-----------+--------------+
| 1 | 3 | 3 | 3045 | 20-05-2016 |
| 2 | 5 | 45 | 3025 | 01-03-2016 |
| 3 | 4 | 63 | 3098 | 05-05-2016 |
| 4 | 5 | 5 | 3041 | 03-04-2016 |
| 5 | 3 | 97 | 3092 | 22-02-2016 |
| 6 | 1 | 22 | 3086 | 24-11-2016 |
| 7 | 9 | 24 | 3085 | 15-12-2016 |
+----+------------------+--------+-----------+--------------+
I need to write trigger that checks before the new row is inserted to the table if the table already has row with columns values 'ObjectId' and 'DateReview' that equal to the columns values of the row that have to be inserted, if it's equal I need to get the ID of the exited row and to put to trigger variable called duplicate .
For example, if new row that has to be inserted is:
INSERT INTO InspectionsReview (InspectionItemId, SiteId, ObjectId, DateReview)]
VALUES (4, 63, 3098, '05-05-2016');
The duplicate variable in SQL Server trigger must be equal to 3.
Because the row in InspectionsReview table were ID = 3 has ObjectId and DateReview values the same as in new row that have to be inserted. How can I implement this?
With the extra assumption that you want to log all the duplicate to a different table, then my solution would be to create an AFTER trigger that would check for the duplicate and insert it into your logging table.
Of course, whether this is the solution depends on whether my extra assumption is valid.
Here is my logging table.
CREATE TABLE dbo.InspectionsReviewLog (
ID int
, ObjectID int
, DateReview DATETIME
, duplicate int
);
Here is the trigger (pretty straightforward with the extra assumption)
CREATE TRIGGER tr_InspectionsReview
ON dbo.InspectionsReview
AFTER INSERT
AS
BEGIN
DECLARE #tableVar TABLE(
ID int
, ObjectID int
, DateReview DATETIME
);
INSERT INTO #tableVar (ID, ObjectID, DateReview)
SELECT DISTINCT inserted.ID, inserted.ObjectID, inserted.DateReview
FROM inserted
JOIN dbo.InspectionsReview ir ON inserted.ObjectID=ir.ObjectID AND inserted.DateReview=ir.DateReview AND inserted.ID <> ir.ID;
INSERT INTO dbo.InspectionsReviewLog (ID, ObjectID, DateReview, duplicate)
SELECT ID, ObjectID, DateReview, 3
FROM
#tableVar;
END;
I am looking to pull data from a table and insert the results into a #temp table where the column name is part of the result set. I know I can get the column names from the schema information table but I need the data in one of the columns. There will be only 1 row from the original table, so I am basically doing a reverse STUFF command or reverse Pivot. The result set would be columnName and Value but multiple rows- as many rows as columns
So basically the result set or table with have just 2 columns, one for the column name and one for the value in that column. That is my goal. I know a pivot does this in reverse but can't seem to find a "Reverse pivot". I am using SQL Server 2008.
Any help would be appreciated. Thanks!
Are you able to give a better description of what you're after? For example, more information on the table structures, etc.
Regardless. Please see below an example of using a CROSS APPLY statement to transform a 'Pivot Table' into a flat table.
Data within the pivot table
+----+-----------+----------+----------------+
| Id | FirstName | LastName | Company |
+----+-----------+----------+----------------+
| 1 | Joe | Bloggs | A Company |
| 2 | Jane | Doe | Lost and Found |
+----+-----------+----------+----------------+
SQL statement to turn pivot table to flat table
IF OBJECT_ID('PivotedTable', 'U') IS NOT NULL
DROP TABLE PivotedTable
GO
CREATE TABLE PivotedTable (
Id INT IDENTITY,
FirstName VARCHAR(255),
LastName VARCHAR(255),
Company VARCHAR(255)
)
INSERT PivotedTable (FirstName, LastName, Company)
VALUES ('Joe', 'Bloggs', 'A Company'), ('Jane', 'Doe', 'Lost and Found')
SELECT
FlatTable.ColumnName,
FlatTable.Value
FROM PivotedTable t
CROSS APPLY (
VALUES
('FirstName', FirstName),
('LastName', LastName),
('Company', Company)
) FlatTable (ColumnName, Value)
Output of the query after turning into a flat table
+------------+----------------+
| ColumnName | Value |
+------------+----------------+
| FirstName | Joe |
| LastName | Bloggs |
| Company | A Company |
| FirstName | Jane |
| LastName | Doe |
| Company | Lost and Found |
+------------+----------------+
I'm trying to write a stored procedure which takes in a table type parameter and inserts into two tables at once.
I have an entity table which is a base table holding the id for various tables, below is the entity table and a sample Site table.
------ Entity Table ------------------------------------------
| Id | bigint | NOT NULL | IDENTITY(1,1) | PRIMARY KEY
| TypeId | tinyint | NOT NULL |
| Updated | datetime | NULL |
| Created | datetime | NOT NULL |
| IsActive | bit | NOT NULL |
------- Site Table ---------------------------------------
| EntityId | bigint | NOT NULL | PRIMARY KEY
| ProductTypeCode | nvarchar(8) | NOT NULL | PRIMARY KEY
| SupplierCode | nvarchar(8) | NOT NULL | PRIMARY KEY
| Name | nvarchar(128) | NOT NULL |
| Description | nvarchar(max) | NULL |
And here is my table type used to pass into the stored procedure
------- Site Table Type ----------------------------------
| EntityTypeId | tinyint | NOT NULL |
| ProductTypeCode | nvarchar(8) | NOT NULL | PRIMARY KEY
| SupplierCode | nvarchar(8) | NOT NULL | PRIMARY KEY
| Name | nvarchar(128) | NOT NULL |
| Description | nvarchar(max) | NULL |
The idea is that I will pass in a table type parameter into the stored procedure and insert multiple rows at once to save looping inserting one row at a time.
Here's what I have so far
CREATE PROCEDURE InsertSites
#Sites SiteTypeTable READONLY
AS
BEGIN
-- Insert into Entity & Site Tables here, using the Id from the Entity Table in the Site table
INSERT INTO Entity (TypeId, Updated, Created, IsActive)
OUTPUT [inserted].[Id], S.ProductTypeCode, S.SupplierCode, S.Name, S.Description
INTO Site
SELECT EntityTypeId, NULL, GETDATE(), 1
FROM #Sites S
END
I've read about using insert and output together but cannot get this to work. I've also read about merge but also cannot get this to work.
Any help or pointers you can give will be greatly appreciated.
Thanks
Neil
---- Edit ----
Could I do something like this? I'm not sure how to finish this off...
CREATE PROCEDURE InsertSites
#Sites SiteTypeTable READONLY
AS
BEGIN
-- First insert enough rows into Entity table, saving the inserted Ids to a table variable
DECLARE #InsertedOutput TABLE (EntityId bigint)
INSERT INTO Entity (TypeId, Updated, Created, IsActive)
OUTPUT [inserted].[id]
INTO #InsertedOutput
SELECT EntityTypeId, NULL, GETDATE(), 1
FROM #Sites S
-- Use the Ids in #InsertedOutput against the rows in #Sites to insert into Sites
END