dbeaver / dbeaver

Free universal database tool and SQL client

Home Page:https://dbeaver.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Option to choose between truncate and delete in data transfer task (SQL Server issue)

krasucki opened this issue · comments

commented

System information:

  • Windows 10
  • DBeaver version 7.2.5

Connection specification:

  • SQL Server v2019

Describe the problem you're observing:

In some cases, when target table is referenced by foreign key constraint, we can't truncate data. This is because SQL Server requires different approach to disable that kind of check (as opposed here #9396).
We can not simply disable constraints (i.e. ALTER TABLE <table> NOCHECK CONSTRAINT ALL) and get truncate to work. What is required, is that, we need to delete foreign key constraint completely and then recreate it after transfer is complete.
Now, I know it can be a lot of work for you, but what I'm suggesting is the option to delete data and re-seed the table.

DELETE from "<table>";
DBCC CHECKIDENT("<table>", RESEED, 0);

This way, data integrity check will pass without any alternation. Simple and easy solution given as an option.

Steps to reproduce, if exist:

  • create data transfer task to target table referenced by foreign key constraint
  • check truncate target table option
    image

Include any warning/errors/backtraces from the logs

image

@krasucki Thank you for the suggestion, we will look if it can be implemented

commented

@Matvey16 Thank you, some things to consider:

  • can be slower than truncate
  • creates transactional log for each deleted row, therefore requires more disk space - unless transactions are skipped
  • can activate triggers (if any) - unless triggers are disabled

basically this is DML vs DDL operation

Sorry, but your idea is not clear for now.

You can use ALTER TABLE <table> NOCHECK CONSTRAINT ALL as "Disable referential integrity" in DBeaver data transfer settings. But it does not work in your case?

2022-06-17 14_36_51-Data Transfer

And you want another solution with this statement:
DBCC CHECKIDENT("<table>", RESEED, 0);

But how does it work? As I can see it works for identity columns. It didn't help me with the foreign keys problem (value '5' is out of possible values):

2022-06-17 14_37_59-DBeaver Ultimate 22 1 0 - master Script-196

For now, your request looks too specific for DBeaver universal data transfer to Implement.

@LonwoLonwo , I didn't saw option to disable integrity check in my version of DBeaver (I was using 7.2.5). Installed recent version, checked this option, but still it is not working as expected. I can recreate this issue using structure below.

The tables with '_src' suffix are source in the same database - just for simplification.

USE test_db;

create table building_src (
	id int IDENTITY(1,1) NOT NULL,
	address nvarchar(100), 
	CONSTRAINT PK_building_src PRIMARY KEY (id) 
)

create table dept_src (
	id int IDENTITY(1,1) NOT NULL,
	name nvarchar(100), 
	building_id int not null,
	CONSTRAINT PK_dept_src PRIMARY KEY (id) ,
	CONSTRAINT FK_building_src FOREIGN KEY (building_id) REFERENCES building_src(id)
)

create table empl_src (
	id int IDENTITY(1,1) NOT NULL,
	name nvarchar(100),
	dept_id int NOT NULL,
	CONSTRAINT PK_empl_src PRIMARY KEY (id),
	CONSTRAINT FK_empl_src FOREIGN KEY (dept_id) REFERENCES dept_src(id)
)

create table building (
	id int IDENTITY(1,1) NOT NULL,
	address nvarchar(100), 
	CONSTRAINT PK_building PRIMARY KEY (id) 
)

create table dept (
	id int IDENTITY(1,1) NOT NULL,
	name nvarchar(100), 
	building_id int not null,
	CONSTRAINT PK_dept PRIMARY KEY (id) ,
	CONSTRAINT FK_building FOREIGN KEY (building_id) REFERENCES building(id)
)

create table empl (
	id int IDENTITY(1,1) NOT NULL,
	name nvarchar(100),
	dept_id int NOT NULL,
	CONSTRAINT PK_empl PRIMARY KEY (id),
	CONSTRAINT FK_empl FOREIGN KEY (dept_id) REFERENCES dept(id)
)

 
INSERT INTO building_src (address) VALUES ('B1'), ('B2'), ('B3')
INSERT INTO dept_src (name, building_id) VALUES ('D1', 1), ('D2', 2), ('D3', 3)
INSERT INTO empl_src (name, dept_id) VALUES ('E1', 1), ('E2', 2), ('E3', 3)

Now, having sample data, create export task as follow:
image
image

Running this task gives me following error
image

As for the alternative way (delete-reseed) - it works, but requires specific order of execution, i.e

DELETE FROM empl
DBCC CHECKIDENT('empl', RESEED, 0)
DELETE FROM dept
DBCC CHECKIDENT('dept', RESEED, 0)
DELETE FROM building
DBCC CHECKIDENT('building', RESEED, 0)

and then insert in opposite way

INSERT INTO building (address) VALUES ('B1'), ('B2'), ('B3')
INSERT INTO dept (name, building_id) VALUES ('D1', 1), ('D2', 2), ('D3', 3)
INSERT INTO empl (name, dept_id) VALUES ('E1', 1), ('E2', 2), ('E3', 3)

I know it looks specific, but just thinking if this kind of ordering can be achieved / related to ordering in Tables mapping -
image

hope this helps

One thing to note - after i received Task execution failed error, when I immediately enter task properties (Edit Task) I see 'Disable referential integrity check' field is greyed out. And this is random afaik :(
image
When I reopen the dialog everything is back to normal.

EDIT: OT- sorry, used my second github account..

Ok, thanks for the explanation.
Looks interesting but is very SQL Server-specific for our data transfer.
Maybe someday, we will come up with a good way to integrate DB-specific requests.