Can anyone explain when using sqlpackage.exe to produce a migration script always wants to drop the table and recreate when adding a field.
My databases are hosted on Azure PaaS service.
I have a database with a table created with the following sql:
CREATE TABLE [dbo].[test] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Field 1] INT NULL,
[Timestamp] ROWVERSION NOT NULL,
[InsertedTime] DATETIME DEFAULT (getdate()) NOT NULL,
[UpdatedTime] DATETIME NULL,
[LastUpdatedBy] NVARCHAR (100) NULL,
[AssignedTo] NVARCHAR (90) NULL,
[ActionRequired] NVARCHAR (MAX) NULL,
[AuditLog] XML NULL,
PRIMARY KEY NONCLUSTERED ([Id] ASC)
);
I then create a new temporary database and run the following sql (adding field 2)
CREATE TABLE [dbo].[test] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Field 1] INT NULL,
[Field 2] INT NULL,
[Timestamp] ROWVERSION NOT NULL,
[InsertedTime] DATETIME DEFAULT (getdate()) NOT NULL,
[UpdatedTime] DATETIME NULL,
[LastUpdatedBy] NVARCHAR (100) NULL,
[AssignedTo] NVARCHAR (90) NULL,
[ActionRequired] NVARCHAR (MAX) NULL,
[AuditLog] XML NULL,
PRIMARY KEY NONCLUSTERED ([Id] ASC)
);
Then run the following command to extract the dacpac:
sqlpackage.exe /SourceConnectionString:"<tempdb>" /a:Extract /tf:local.dacpac
Then run this to get a migration report:
sqlpackage.exe /TargetConnectionString:"<orginaldb>" /a:DeployReport /sourcefile:local.dacpac /outputpath:report.xml
But it always wants to do this:
<?xml version="1.0" encoding="utf-8"?>
<DeploymentReport xmlns="http://schemas.microsoft.com/sqlserver/dac/DeployReport/2012/02">
<Alerts>
<Alert Name="DataMotion">
<Issue Value="[dbo].[test]" />
</Alert>
</Alerts>
<Operations>
<Operation Name="TableRebuild">
<Item Value="[dbo].[test]" Type="SqlTable" />
</Operation>
</Operations>
</DeploymentReport>
This probably happens because the new column is not the last column in the table (it is before other existing columns). In such a case also the SSMS Table Designer needs to recreate the table (to preserve the specified order of columns).
Specify the following property when performing the deploy and it won't rebuild the table.
IgnoreColumnOrder=(BOOLEAN 'False')
https://learn.microsoft.com/en-us/sql/tools/sqlpackage/sqlpackage-publish?view=sql-server-ver16#:~:text=IgnoreColumnOrder%3D(BOOLEAN%20%27False%27)
so
sqlpackage.exe /TargetConnectionString:"<orginaldb>" /a:DeployReport /sourcefile:local.dacpac /outputpath:report.xml /p:IgnoreColumnOrder=true
The behavior of sqlpackage.exe can be influenced very detailed by many parameters, here are only a few shown:
A detailed list of all parameters you can find here:
https://learn.microsoft.com/en-us/sql/tools/sqlpackage/sqlpackage-deploy-drift-report?view=sql-server-ver15
It takes likely some time and thoughts to adjust it exactly to your needs.
Related
I created a SQLite 3 db from an existing SQL Express DB. The primary keys in the new SQLite db are type INTEGER, the foreign keys are type int. EF throws a 13101 error.
Example
CREATE TABLE Test (
TestID INTEGER NOT NULL,
TestName NVARCHAR (50),
TestTypeId INT,
TestConfigId INT,
Description NVARCHAR (255),
NumberOfRuns INT,
Modified ROWVERSION NOT NULL,
CONSTRAINT PK_Tests PRIMARY KEY (
TestID
),
FOREIGN KEY (
TestConfigId
)
REFERENCES TestConfiguration (TestConfigID) ON DELETE NO ACTION
ON UPDATE NO ACTION,
FOREIGN KEY (
TestTypeId
)
REFERENCES TestType (TestTypeID) ON DELETE NO ACTION
ON UPDATE NO ACTION
);
CREATE TABLE TestType (
TestTypeID INTEGER NOT NULL,
TestTypeName NVARCHAR (50) NOT NULL,
Description NVARCHAR (50) NOT NULL,
Modified ROWVERSION NOT NULL,
CONSTRAINT PK_TestTypes PRIMARY KEY (
TestTypeID
)
);
In table Test, TestTypeId is an int and a FK, but in table TestTypes TestTypeID is an INTEGER and EF 6.2says they are of different types.
So is the answer to change all the PK's to int and make them AUTO_INCREMENT or change all the PK's to INTEGER?
Thanks,
Doug
Executing the following SQL script in the server:
ERROR: Error 1215: Cannot add foreign key constraint
SQL Code:
CREATE TABLE IF NOT EXISTS `telecom`.`jobreq` (
`id` INT NOT NULL,
`jobName` VARCHAR(45) NULL,
`priority` VARCHAR(45) NULL,
`dates` DATE NULL,
`status` VARCHAR(45) NULL,
`user` VARCHAR(45) NULL,
`timestamp` DATE NULL,
`service_id` INT(11) NOT NULL,
`client_id` INT(11) NOT NULL,
PRIMARY KEY (`id`, `service_id`, `client_id`),
INDEX `fk_jobreq_service1_idx` (`service_id` ASC),
INDEX `fk_jobreq_client1_idx` (`client_id` ASC),
CONSTRAINT `fk_jobreq_service1`
FOREIGN KEY (`service_id`)
REFERENCES `telecom`.`service` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_jobreq_client1`
FOREIGN KEY (`client_id`)
REFERENCES `telecom`.`client` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
SQL script execution finished: statements: 12 succeeded, 1 failed
Fetching back view definitions in final form.
Nothing to fetch
I am unable to find out why I am getting this error can someone with a high intelligence please assist me.
So it seems all I had to do was to change the name of the table and it went through im guessing somehow the name was magically somehow still in the system
I have two tables:
create table Clients
(
id_client int not null identity(1,1) Primary Key,
name_client varchar(10) not null,
phone_client int not null
)
create table Sales
(
id_sale int not null identity(1,1) Primary Key,
date_sale date not null,
total_sale float not null
id_clients int not null identity(1,1) Foreign Key references Clients
)
So, let's insert into Clients ('Ralph', 00000000), the id_client is going to be 1 (obviously). The question is: How could I insert that 1 into Sales?
FIrst of all - you cannot have two columns defined as identity in any table - you will get an error
Msg 2744, Level 16, State 2, Line 1
Multiple identity columns specified for table 'Sales'. Only one identity column per table is allowed.
So you will not be able to actually create that Sales table.
The id_clients column in the Sales table references an identity column - but in itself, it should not be defined as identity - it gets whatever value your client has.
create table Sales
(
id_sale int not null identity(1,1) Primary Key,
date_sale date not null,
total_sale float not null
id_clients int not null foreign key references clients(id_client)
)
-- insert a new client - this will create an "id_client" for that entry
insert into dbo.Clients(name_client, phone_client)
values('John Doe', '+44 44 444 4444')
-- get that newly created "id_client" from the INSERT operation
declare #clientID INT = SCOPE_IDENTITY()
-- insert the new "id_client" into your sales table along with other values
insert into dbo.Sales(......, id_clients)
values( ......., #clientID)
This works for me like a charm, because as far as I understand, if I migrate user or customer data etc from an old copy of the database, - the identity column and the UId(user id) or CId(customer id) used to give each row it's own unique identity - will become unsynced and therefor I use the second column(TId/UId etc) that contains a copy of the identity column's value to relate my data purely through app logic flow.
I can offset the actual SQL Identity Column(IdColumn) when a migration takes place via inserting and deleting dummy data to the count of the largest number found in that TId/CId etc column with the old data to increment the new database table(s) identity column(s) away from having duplicates on new inserts by using the dummy inserts to push the identity column up to old data values and therefor new customers or users etc will continue to source unique values from the identity column upon new inserts after being filled with the old data which will still contain the old identity values in the second column so that the other data(transactions etc) in other tables will still be in sync with which customer/user is related to said data, be it a transaction or whatever. But not have duplicates as the dummy data will have pushed up the IdColumn value to match the old data.
So if I have say 920 user records and the largest UId is 950 because 30 got deleted. Then I will dummy insert and delete 31 rows into the new table before adding the old 920 records to ensure UId's will have no duplicates.
It is very around the bush, but it works for my limited understanding of SQL XD
What this also allows me to do is delete a migrated user/customer/transaction at a later time using the original UId/CId/TId(copy of identity) and not have to worry that it will not be the correct item being deleted if I did not have the copy and were to be aiming at the actual identity column which would be out of sync if the data is migrated data(inserted into database from old database). Having a copy = happy days. I could use (SET IDENTITY_INSERT [dbo].[UserTable] ON) but I will probably screw that up eventually, so this way is FOR ME - fail safe.
Essentially making the data instance agnostic to an extent.
I use OUTPUT inserted.IdColumn to then save any pictures related using that in the file name and am able to call them specifically for the picture viewer and that data is also migration safe.
To do this, a copy, specifically at insert time, is working great.
declare #userId INT = SCOPE_IDENTITY() to store the new identity value-UPDATE dbo.UserTable to select where to update all in this same transaction
-SET UId = #userId to set it to my second column
-WHERE IdColumn = #userId; to aim at the correct row
USE [DatabaseName]
GO
/****** Object: StoredProcedure [dbo].[spInsertNewUser] Script Date:
2022/02/04 12:09:19 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spInsertNewUser]
#Name varchar(50),
#PhoneNumber varchar(20),
#IDNumber varchar(50),
#Address varchar(200),
#Note varchar(400),
#UserPassword varchar(MAX),
#HideAccount int,
#UserType varchar(50),
#UserString varchar(MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO dbo.UserTable
([Name],
[PhoneNumber],
[IDNumber],
[Address],
[Note],
[UserPassword],
[HideAccount],
[UserType],
[IsDeleted],
[UserString])
OUTPUT inserted.IdColumn
VALUES
(#Name,
#PhoneNumber,
#IDNumber,
#Address,
#Note,
#UserPassword,
#HideAccount,
#UserType,
#UserString);
declare #userId INT = SCOPE_IDENTITY()
UPDATE dbo.UserTable
SET UId = #userId
WHERE IdColumn = #userId;
END
Here is the create for the table for testing
CREATE TABLE [dbo].[UserTable](
[IdColumn] [int] IDENTITY(1,1) NOT NULL,
[UId] [int] NULL,
[Name] [varchar](50) NULL,
[PhoneNumber] [varchar](20) NULL,
[IDNumber] [varchar](50) NULL,
[Address] [varchar](200) NULL,
[Note] [varchar](400) NULL,
[UserPassword] [varchar](max) NULL,
[HideAccount] [int] NULL,
[UserType] [varchar](50) NULL,
[IsDeleted] [int] NULL,
[UserString] [varchar](max) NULL,
CONSTRAINT [PK_UserTable] PRIMARY KEY CLUSTERED
(
[IdColumn] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
I'm migrating a Simple Membership database to Identity 2.0. I'm copying a CreateDate datetime NULL column to a CreateDate datetime NOT NULL column. I've examined all the records in the Membership.CreateDate column in the data source table to verify that they contain valid DateTimes. This error is returned:
Cannot insert the value NULL into column 'CreateDate', table 'Settlement.dbo.AspNetUsers'; column does not allow nulls. INSERT fails.
The statement has been terminated.
I've also tried deleting all the records in Membership but one (its CreateDate column contains 2012-12-27 01:35:03.610). I get the same error.
I'm running the script in SSMS.
Migration script excerpts:
CREATE TABLE [dbo].[AspNetUsers] (
[Id] [nvarchar](60) NOT NULL,
[UserName] [nvarchar](15) NOT NULL,
[AcId] INT NOT NULL,
[LocId] INT NOT NULL,
[CreateDate] [datetime] NOT NULL,
[Email] [nvarchar](60),
[EmailConfirmed] [bit] Default ((0)) NOT NULL,
[PasswordHash] [nvarchar] (100),
[SecurityStamp] [nvarchar] (60),
[PhoneNumber] [nvarchar] (15),
[PhoneNumberConfirmed] [bit] Default ((0)) NOT NULL,
[TwoFactorEnabled] [bit] Default ((0)) NOT NULL,
[LockoutEndDateUtc] [datetime],
[LockoutEnabled] [bit] Default ((0)) NOT NULL,
[AccessFailedCount] [int] Default ((0)) NOT NULL,
CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY ([Id])
);
GO
INSERT INTO AspNetUsers(Id, UserName, AcId, LocId, PasswordHash, SecurityStamp, CreateDate )
SELECT UserProfile.UserId, UserProfile.UserName, UserProfile.BaId, UserProfile.OfcId,
webpages_Membership.Password, webpages_Membership.PasswordSalt, webpages_Membership.CreateDate
FROM UserProfile
LEFT OUTER JOIN webpages_Membership ON UserProfile.UserId = webpages_Membership.UserId
GO
If I change the AspNetUsers CreateDate column to NULL it successfully copies the datetimes from table to table so I know all the column names and types are correct.
(After doing this I ran
ALTER TABLE [dbo].[AspNetUsers] ALTER COLUMN [CreateDate] datetime NOT NULL
and got the same error)
This is happening with the Production copy of the database. I have a development copy of the database generated through the same EF code first code and it successfully copies the data into the CreateDate NOT NULL field.
I'm at wits end at this point. Why am I getting a Cannot insert the value NULL into column error when the source data is valid datetimes? Or why doesn't it recognize the CreateDate columns data as valid datetimes?
You have some users in the UserProfile that haven't corresponding users in the webpages_Membership, so you try to insert users without any information. You must use INNER JOIN instead of LEFT OUTER JOIN or provide the default values for users which haven't corresponding information.
Hy I have problem. I wanna to create table with some atributes, and some of them shoud be specified as NOT NULL.. And here comes the problem. When I insert some data into table, and when I insert '' (empty single string) it input data into table, but I dont want this... How to restrict inserting data from inputing single string or inputing nothing..
here are my table
CREATE TABLE tbl_Film
(
ID INT UNSIGNED PRIMARY KEY,
Naziv VARCHAR(50) NOT NULL,
Zanr VARCHAR(50) NOT NULL,
Opis VARCHAR(150) NULL,
Kolicina INT UNSIGNED NOT NULL
);
INSERT INTO tbl_Film VALUES (1,'','Animirani','Mala ribica',2)
This input blank data into Naziv, and I don't want that.. I need to restrict that..
http://prntscr.com/21gfgd
I dont know if this is possible in SQL, but why dont you exchange the '' in your application into the String NULL?
In SQL, NULL is not the same as '' (with the exception of MS SQL via OleDB AFAIR, in which '' should be stored as NULL).
NULL values represent missing unknown data.
See http://www.w3schools.com/sql/sql_null_values.asp
In regular SQL, you should use a CHECK constraint, e.g.
CREATE TABLE tbl_Film (
ID INT UNSIGNED PRIMARY KEY,
Naziv VARCHAR(50) NOT NULL,
Zanr VARCHAR(50) NOT NULL,
Opis VARCHAR(150) NULL,
Kolicina INT UNSIGNED NOT NULL,
CHECK (Naziv <> '')
);
Sadly, this CHECK constraint is NOT implemented by MySQL:
The CHECK clause is parsed but ignored by all storage engines.
See http://dev.mysql.com/doc/refman/5.7/en/alter-table.html
So the only solution I see, at DB level, is to write a P/SQL trigger...