无论如何,这是针对 SQL Server 2022 的。该错误仅在运行时发生,并且仅当我右键单击列表中的存储过程并选择执行时发生。
当我单击执行按钮时,它运行没有问题。当我单击解析按钮时,它成功完成。所以这严格来说是一个运行时错误。
DECLARE IndexCursor CURSOR FOR
SELECT PersonID AS NewUserID
FROM Person as tblUser
OPEN IndexCursor
FETCH NEXT FROM IndexCursor INTO @UserID
INSERT INTO Workout (PersonID, ExerciseID, ExerciseTypeID)
SELECT *
FROM Exercise A
WHERE NOT EXISTS (SELECT @UserID, A.ExcerciseID, A.ExerciseTypeID
FROM Workout B
WHERE A.ExcerciseID = B.ExerciseID
)
我已将问题范围缩小到 where 子句。如果我注释掉它,我不会收到错误,但它也会在所有数据上运行。
这将运行光标来抓取每个
userid
,并抓取它以便可以将其用于填充锻炼表。其他数据已经在练习表中了。
这个想法是,如果添加了一项锻炼,它会将该锻炼添加到数据库中每个人的锻炼中。所有字段和变量都设置为 uniqueidentifier,所以我真的不知道为什么它必须将任何内容转换为它应该已经设置的内容。
我确实发现 where 子句的两个字段存在差异,但我不知道如何修复它。
B.ExerciseID
有默认值 (newid()
),A.exercise
列没有。
我知道我的“exercise”有拼写错误,我需要去修改这些错误。哈哈
我在所有出现的情况下都尝试过
CAST
和 CONVERT
上的 @UserID
。我已经在 CAST
和 A.Exercise
上依次和同时尝试了 B.Exercise
。我不断地用谷歌搜索不同的想法。我已经注释掉了部分代码,以缩小导致问题的实际行范围(直到我这样做,我才意识到 @UserID
变量实际上并没有导致问题)
更新:
CREATE TABLE [dbo].[Person]
(
[PersonID] [uniqueidentifier] NOT NULL,
[Name] [varchar](50) NOT NULL,
[Weight] [smallint] NOT NULL,
[GoalWeight] [smallint] NOT NULL,
CONSTRAINT [PK_Person]
PRIMARY KEY CLUSTERED ([PersonID] ASC)[PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Workout]
(
[WrokoutID] [uniqueidentifier] NOT NULL,
[PersonID] [uniqueidentifier] NOT NULL,
[ExerciseID] [uniqueidentifier] NOT NULL,
[ExerciseTypeID] [uniqueidentifier] NOT NULL,
[Weight] [smallint] NOT NULL,
[Reps] [smallint] NOT NULL,
[Sets] [smallint] NOT NULL,
[NumberOfTimesCompleted] [bigint] NOT NULL,
[DateOfLastCompletion] [date] NOT NULL,
[Notes] [nvarchar](max) NULL,
CONSTRAINT [PK_Workout]
PRIMARY KEY CLUSTERED ([WrokoutID] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[Workout]
ADD CONSTRAINT [DF_Workout_WrokoutID]
DEFAULT (NEWID()) FOR [WrokoutID]
GO
ALTER TABLE [dbo].[Workout]
ADD CONSTRAINT [DF_Workout_ExerciseID]
DEFAULT (NEWID()) FOR [ExerciseID]
GO
ALTER TABLE [dbo].[Workout]
ADD CONSTRAINT [DF_Workout_Weight]
DEFAULT ((0)) FOR [Weight]
GO
ALTER TABLE [dbo].[Workout]
ADD CONSTRAINT [DF_Workout_Reps]
DEFAULT ((0)) FOR [Reps]
GO
ALTER TABLE [dbo].[Workout]
ADD CONSTRAINT [DF_Workout_Sets]
DEFAULT ((0)) FOR [Sets]
GO
ALTER TABLE [dbo].[Workout]
ADD CONSTRAINT [DF_Workout_NumberOfTimesCompleted]
DEFAULT ((0)) FOR [NumberOfTimesCompleted]
GO
ALTER TABLE [dbo].[Workout]
ADD CONSTRAINT [DF_Workout_DateOfLastCompletion]
DEFAULT (GETDATE()) FOR [DateOfLastCompletion]
GO
ALTER TABLE [dbo].[Workout] WITH CHECK
ADD CONSTRAINT [FK_ExcerciseNameToWorkout]
FOREIGN KEY([ExerciseID])
REFERENCES [dbo].[Exercise] ([ExcerciseID])
GO
ALTER TABLE [dbo].[Workout] CHECK CONSTRAINT [FK_ExcerciseNameToWorkout]
GO
ALTER TABLE [dbo].[Workout] WITH CHECK
ADD CONSTRAINT [FK_ExerciseTypeToWorkout]
FOREIGN KEY([ExerciseTypeID])
REFERENCES [dbo].[ExerciseType] ([ExerciseTypeID])
GO
ALTER TABLE [dbo].[Workout] CHECK CONSTRAINT [FK_ExerciseTypeToWorkout]
GO
ALTER TABLE [dbo].[Workout] WITH CHECK
ADD CONSTRAINT [FK_WorkoutToPerson]
FOREIGN KEY([PersonID])
REFERENCES [dbo].[Person] ([PersonID])
GO
ALTER TABLE [dbo].[Workout] CHECK CONSTRAINT [FK_WorkoutToPerson]
GO
USE [WorkoutTracker]
GO
/****** Object: Table [dbo].[Exercise] Script Date: 10/27/2024 10:37:47 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Exercise](
[ExcerciseID] [uniqueidentifier] NOT NULL,
[ExerciseName] [varchar](50) NOT NULL,
[ExerciseTypeID] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_Exercise] PRIMARY KEY CLUSTERED
(
[ExcerciseID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Exercise] ADD CONSTRAINT [DF_Exercise_ExcerciseID] DEFAULT (newid()) FOR [ExcerciseID]
GO
ALTER TABLE [dbo].[Exercise] WITH CHECK ADD CONSTRAINT [FK_ExcerciseTypeToExcercise] FOREIGN KEY([ExerciseTypeID])
REFERENCES [dbo].[ExerciseType] ([ExerciseTypeID])
GO
ALTER TABLE [dbo].[Exercise] CHECK CONSTRAINT [FK_ExcerciseTypeToExcercise]
GO
玩完这个之后我选择了一个完全不同的方向。我使用 if 语句来检查丢失的记录,然后如果有任何记录,我会逐步收集信息。然后将其全部插入到最后的表中。这是成品。我知道它很丑陋,并且希望得到有关如何减少混乱的建议,例如我使用了超过三次的同一个 select 子句。
USE [WorkoutTracker]
GO
/****** Object: StoredProcedure [dbo].[UpdateUserWorkouts] Script Date: 10/27/2024 10:28:37 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[UpdateUserWorkouts]
-- Add the parameters for the stored procedure here
AS
SET NOCOUNT ON;
IF EXISTS (
SELECT Exercise.ExcerciseID, Exercise.ExerciseTypeID
FROM dbo.Exercise LEFT OUTER JOIN
dbo.Workout ON dbo.Exercise.ExcerciseID = dbo.Workout.ExerciseID
WHERE (dbo.Workout.WrokoutID IS NULL)
)
BEGIN
DECLARE @UserID uniqueidentifier
DECLARE @ExerciseID uniqueidentifier
DECLARE @ExerciseTypeID uniqueidentifier
SET @ExerciseID = (SELECT Exercise.ExcerciseID FROM dbo.Exercise LEFT OUTER JOIN dbo.Workout ON dbo.Exercise.ExcerciseID = dbo.Workout.ExerciseID WHERE (dbo.Workout.WrokoutID IS NULL))
SET @ExerciseTypeID = (SELECT Exercise.ExerciseTypeID FROM dbo.Exercise LEFT OUTER JOIN dbo.Workout ON dbo.Exercise.ExcerciseID = dbo.Workout.ExerciseID WHERE (dbo.Workout.WrokoutID IS NULL))
DECLARE IndexCursor CURSOR FOR
SELECT PersonID AS NewUserID
FROM Person as tblUser
OPEN IndexCursor
FETCH NEXT FROM IndexCursor INTO @UserID
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO Workout
(
PersonID
, ExerciseID
, ExerciseTypeID
)
VALUES
(
@UserID
, @ExerciseID
, @ExerciseTypeID
)
FETCH NEXT FROM IndexCursor INTO @UserID
END
Close IndexCursor
DEALLOCATE IndexCursor
END