Вопрос или проблема
В любом случае, это SQL Server Management Studio 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
и захватить его, чтобы он мог использоваться для заполнения таблицы тренировок. Другие данные уже находятся в таблице упражнений.
Идея в том, что если упражнение добавляется, оно будет добавлено к тренировкам каждого человека в базе данных. Все поля и переменные установлены как уникальные идентификаторы, поэтому я действительно не знаю, почему нужно преобразовывать что-то в то, что уже должно быть установлено.
Я нашел одно различие в двух полях предложения WHERE, но не знаю, как это исправить. B.ExerciseID
имеет значение по умолчанию (newid()
), A.exercise
столбец не имеет.
Я знаю, что у меня есть опечатки в слове “упражнение”, мне нужно зайти и исправить это. лол
Я попробовал CAST
и CONVERT
на @UserID
во всех случаях, когда он появляется. Я пробовал CAST
на A.Exercise
и B.Exercise
, поочередно и одновременно. Я искал и искал, гугляя различные идеи. Я закомментировал части кода, чтобы сузить фактическую строку, вызывающую проблему (только когда я это сделал, я понял, что переменная @UserID
на самом деле не вызывала проблему)
Обновление:
USE [WorkoutTracker]
GO
/****** Объект: Таблица [dbo].[Person] Дата скрипта: 10/27/2024 10:02:40 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
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
)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
USE [WorkoutTracker]
GO
/****** Объект: Таблица [dbo].[Workout] Дата скрипта: 10/27/2024 10:04:05 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
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
)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] 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
Ответ или решение
Проблема, с которой вы столкнулись — это ошибка во время выполнения хранимой процедуры в SQL Server Management Studio 2022, связанная с преобразованием строкового значения в тип данных uniqueidentifier
. Этот тип ошибки может возникнуть по нескольким причинам, что мы и рассмотрим в данной статье.
1. Проблема с исходным кодом
Из вашего описания видно, что проблема возникает, когда вы выполняете хранимую процедуру, а не при её компиляции или разборе, что указывает на наличие неявного преобразования типов данных в момент выполнения. Ниже приведён код, с которым вы работаете:
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)
Здесь можно выделить несколько ключевых моментов:
@UserID
— это переменная типаuniqueidentifier
, которая должна быть совместима с полемPersonID
в таблицеWorkout
.- В данном случае ошибка преобразования может быть связана с условием в предложении
WHERE
. Давайте рассмотрим его более подробно.
2. Анализ предложения WHERE
Ваша проверка в условии WHERE NOT EXISTS
может вызывать проблемы из-за неправильно указанных типов данных или даже ошибок в написании. В вашем коде есть опечатка: вы пишете A.ExcerciseID
вместо A.ExerciseID
. Это может приводить к ошибкам, когда SQL Server пытается определить, существует ли поле с указанным именем, и, возможно, не может сопоставить его с типом данных.
3. Проверка корректности индексов и уникальности
Поскольку оба столбца в вашем условии являются uniqueidentifier
, важно также убедиться, что данные в столбцах совпадают по типу и значению. Необходимо проверить целостность данных:
- Убедитесь, что данные, хранящиеся в таблице
Workout
дляPersonID
, соответствуют данным, получаемым изtblUser
. - Убедитесь, что переменная
@UserID
, полученная из курсора, корректно загружается и используется.
4. Подходы к исправлению
Для дальнейшей диагностики и устранения проблемы, рассмотрите следующие шаги:
-
Проверка значений переменной: Перед установкой в
@UserID
, добавьте временный отладочный код, чтобы проверить, действительно ли@UserID
содержит значения типаuniqueidentifier
.PRINT CAST(@UserID AS VARCHAR(36));
-
Замена NOT EXISTS: Попробуйте переписать условие
WHERE
без использованияSELECT
с подзапросом, например, с помощьюJOIN
, чтобы избежать неявных преобразований. -
Упрощенный запрос: Упростите ваш запрос и поэкспериментируйте с отдельными частями, чтобы изолировать проблему.
5. Заключение
Ошибки типа "не удалось преобразовать строку в uniqueidentifier" могут быть достаточно запутанными и часто возникают из-за несовпадения типов данных или ошибочного использования переменных. При выполнении представленных выше шагов вы сможете более точно определить причину возникновения проблемы и устранить её.
Если при исправлении ошибок проблема останется, рассмотрите добавление более подробного логирования, чтобы углубиться в контекст возникновения ошибки. Надеюсь, что эти рекомендации помогут вам в решении данной проблемы.