正在将 MySQL 过程迁移到 SQL 服务器

Migrating MySQL procedure to SQL Server

所以我正在将数据从 MySQL (MariaDB) 迁移到 SQL Server 2019,并且所有表都迁移正常,但存储过程没有,我想知道导致此错误的原因,因为我从未使用过 SQL 仅服务器 MySQL.

我的错误日志表格SQL Server Migration Assistant for MySQL

Starting Phase #1
Loading to database new procedure SwMetrics.testreportingdebug.AddTestCaseRequirement ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.AddTestResultRequirement ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.BeginTestResults ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.BeginTestRun ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.BeginTestRunWithTestJob ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.CreateJiraLink ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.CreateTarget ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.CreateTestCase ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.CreateTestJob ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.CreateTestResultsJiraLink ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.CreateTestSuite ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.CreateTestSuiteCaseLink ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.CreateTestSuiteCollection ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.CreateTestSuiteCollectionLink ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.CreateVersion ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.EndTestJob ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.EndTestResults ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.EndTestRun ...
  ... sql execution failed
Loading to database new function SwMetrics.testreportingdebug.IsTemporaryName ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.SetStatusName ...
  ... sql execution failed
Loading to database new procedure SwMetrics.testreportingdebug.SetTestJobFinished ...
  ... sql execution failed
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.AddTestCaseRequirement
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.AddTestResultRequirement
 Errors: Incorrect syntax near '`'.
Incorrect syntax near '`'.
Incorrect syntax near '`'.
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name.
Synchronization error: Incorrect syntax near '`'.
Incorrect syntax near '`'.
Incorrect syntax near '`'.
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name. On: SwMetrics.testreportingdebug.BeginTestResults
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.BeginTestRun
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.BeginTestRunWithTestJob
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.CreateJiraLink
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.CreateTarget
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.CreateTestCase
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.CreateTestJob
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.CreateTestResultsJiraLink
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.CreateTestSuite
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.CreateTestSuiteCaseLink
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.CreateTestSuiteCollection
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.CreateTestSuiteCollectionLink
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.CreateVersion
 Errors: Incorrect syntax near '`'.
Synchronization error: Incorrect syntax near '`'. On: SwMetrics.testreportingdebug.EndTestJob
 Errors: Incorrect syntax near '`'.
Synchronization error: Incorrect syntax near '`'. On: SwMetrics.testreportingdebug.EndTestResults
 Errors: Incorrect syntax near '`'.
Synchronization error: Incorrect syntax near '`'. On: SwMetrics.testreportingdebug.EndTestRun
 Errors: Invalid column name '__'.
Invalid column name '__'.
Synchronization error: Invalid column name '__'.
Invalid column name '__'. On: SwMetrics.testreportingdebug.IsTemporaryName
 Errors: DEFAULT or NULL are not allowed as explicit identity values.
Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.SetStatusName
 Errors: Incorrect syntax near '`'.
Synchronization error: Incorrect syntax near '`'. On: SwMetrics.testreportingdebug.SetTestJobFinished
Synchronization operation is complete.

错误 1

失败的 MySQL 存储过程之一的示例 BeginTestRun

CREATE DEFINER=`root`@`localhost` PROCEDURE `BeginTestRun`(StartTime DATETIME, TestJobId INT)
BEGIN
  INSERT INTO TestRuns (`id`,`StartTime`, `TestJobId`)
  VALUES (NULL,StartTime,TestJobId);
  SELECT LAST_INSERT_ID() AS LastInsertId;
END

上面那个有这个错误:

Errors: DEFAULT or NULL are not allowed as explicit identity values.

我应该写什么而不是 NULL?为什么不允许这样做?

错误 2

另一个EndTestRun

CREATE DEFINER=`root`@`localhost` PROCEDURE `EndTestRun`(TestRunId INT, EndTime DATETIME)
BEGIN
  UPDATE TestRuns
  SET `EndTime` = EndTime
  WHERE ID = TestRunId;
  SELECT LAST_INSERT_ID() AS LastInsertId;
END

有这个错误

Synchronization error: Incorrect syntax near '`'. On: SwMetrics.testreportingdebug.EndTestRun Errors: Invalid column name '__'.

我真的不明白 __ 应该在哪里?

错误 3

另一个不同的是CreateVersion

CREATE DEFINER=`edmetrics`@`%` PROCEDURE `CreateVersion`(varName varchar(100), Version varchar(100), TargetId INT)
BEGIN

  INSERT INTO Versions(`id`,`Name`,`Version`,`TargetId`)
  VALUES (NULL,varName,Version,TargetId);
  SELECT LAST_INSERT_ID() AS LastInsertId;
END

有错误

Synchronization error: DEFAULT or NULL are not allowed as explicit identity values. On: SwMetrics.testreportingdebug.CreateVersion Errors: Incorrect syntax near '`'.

应该 ` 直接删除,为什么不允许?

Errors: DEFAULT or NULL are not allowed as explicit identity values.

我想 table 中的 id 列是一个标识,这意味着下面的代码应该可以工作。

CREATE PROCEDURE CreateVersion @varName varchar(100), @Version varchar(100), @TargetId INT
AS
BEGIN

  INSERT INTO Versions(Name,Version,TargetId)
  VALUES (@varName,@Version,@TargetId);
  SELECT SCOPE_IDENTITY() AS LastInsertId;
END

First SQL 服务器不接受重音符号(特定于 MySQL)来分隔 SQL 标识符(table、列、程序...等等)。如果您的 SQL 标识符符合标准,您必须使用 SQL ISO 标准双引号或特定的 SQL 服务器定界符(方括号)或什么都不用。所以:

CREATE DEFINER=`root`@`localhost` PROCEDURE `BeginTestRun` ...

必须重写为:

CREATE DEFINER="root`@`localhost" PROCEDURE "BeginTestRun" ...

或:

CREATE DEFINER=[root`@`localhost] PROCEDURE [BeginTestRun] ...

Second DEFINER 是特定的 MySQL terms/object,ISO SQL 标准不知道,Microsoft SQL 服务器也不知道。标准 ISO SQL 中的等价物是自动关联到执行 CREATE 语句的 SQL 用户的对象的所有者。所以:

CREATE DEFINER=`root`@`localhost` PROCEDURE `BeginTestRun` ...

必须重写为:

CREATE PROCEDURE "BeginTestRun" ...

第三,每个变量必须以“@”(arobas / at 符号)为前缀。所以:

CREATE DEFINER=`root`@`localhost` PROCEDURE `BeginTestRun`(StartTime DATETIME, TestJobId INT)

必须重写:

CREATE PROCEDURE [BeginTestRun] (@StartTime DATETIME, @TestJobId INT)

第四,DATETIME 是一种过时的数据类型,最好使用 DATETIME2。所以

CREATE DEFINER=`root`@`localhost` PROCEDURE `BeginTestRun`(StartTime DATETIME, TestJobId INT)

必须重写为:

CREATE PROCEDURE [BeginTestRun] (@StartTime DATETIME2, @TestJobId INT)

Fith, LAST_INSERT_ID() 在 SQL 服务器中不存在,必须用 SCOPE_IDENTITY() 代替。所以:

CREATE DEFINER=`root`@`localhost` PROCEDURE `BeginTestRun`(StartTime DATETIME, TestJobId INT)
BEGIN
  INSERT INTO TestRuns (`id`,`StartTime`, `TestJobId`)
  VALUES (NULL,StartTime,TestJobId);
  SELECT LAST_INSERT_ID() AS LastInsertId;
END

必须重写为:

CREATE PROCEDURE [BeginTestRun] (@StartTime DATETIME2, @TestJobId INT)
BEGIN
  INSERT INTO TestRuns (id, StartTime, TestJobId)
  VALUES (NULL, @StartTime, @TestJobId);
  SELECT SCOPE_IDENTITY() AS LastInsertId;
END

,因为SQL服务器程序默认是在debug模式下创建的,所以一定要优先添加SET NOCOUNT ON语句,避免运行时消息不及时.所以:

CREATE DEFINER=`root`@`localhost` PROCEDURE `BeginTestRun`(StartTime DATETIME, TestJobId INT)
BEGIN
  INSERT INTO TestRuns (`id`,`StartTime`, `TestJobId`)
  VALUES (NULL,StartTime,TestJobId);
  SELECT LAST_INSERT_ID() AS LastInsertId;
END

必须重写为:

CREATE PROCEDURE [BeginTestRun] (@StartTime DATETIME2, @TestJobId INT)
BEGIN
SET NOCOUNT ON;
  INSERT INTO TestRuns (id, StartTime, TestJobId)
  VALUES (NULL, @StartTime, @TestJobId);
  SELECT SCOPE_IDENTITY() AS LastInsertId;
END

第七,当你的table作为一个IDENTITY列时,默认情况下你不能在里面INSERT任何值。因此,如果 table TestRuns 中的列 ID 是 IDENTITY,则不应在插入目标列的列表中指定此列。所以:

CREATE DEFINER=`root`@`localhost` PROCEDURE `BeginTestRun`(StartTime DATETIME, TestJobId INT)
BEGIN
  INSERT INTO TestRuns (`id`,`StartTime`, `TestJobId`)
  VALUES (NULL,StartTime,TestJobId);
  SELECT LAST_INSERT_ID() AS LastInsertId;
END

必须重写为:

CREATE PROCEDURE [BeginTestRun] (@StartTime DATETIME2, @TestJobId INT)
BEGIN
SET NOCOUNT ON;
  INSERT INTO TestRuns (StartTime, TestJobId)
  VALUES (@StartTime, @TestJobId);
  SELECT SCOPE_IDENTITY() AS LastInsertId;
END

当然最好的方法就是学习Transact SQL !