Справка по счетчику SQL - PullRequest
1 голос
/ 15 июля 2011

Мне нужна помощь с моей хранимой процедурой. В настоящее время у меня есть хранимая процедура, принимающая значения и публикующая эти значения в моей базе данных.Это для программы, которая дает студентам тест и записывает их ответы и оценки в базу данных.Я хотел отследить, сколько попыток ученик предпринял в каждой викторине.Мне нужен способ иметь счетчик для каждого студента и для каждого теста.Это моя текущая хранимая процедура, когда я запускаю ее, моя база данных выдает мне эту ошибку Ошибка 170: Строка 17: Неверный синтаксис рядом с «LIMIT».Я также пытался выполнить функцию LAST (), но в базе данных говорилось, что функция LAST () не была распознана.

CREATE PROCEDURE [dbo].spRecordStudentScore
     @StudentNum            BIGINT,
     @TestID               BIGINT,
     @DateCompleted     DATETIME,
     @Score        FLOAT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @Attempt int;

    SET @Attempt = 1;

    BEGIN
    IF NOT EXISTS (SELECT * FROM dbo.tbStudentScores WHERE fdStudent# = @StudentNum AND fdTestID = @TestID AND fdAttempt = @Attempt)
        SET @Attempt = 1;
    ELSE 
        SELECT @Attempt = fdAttempt FROM dbo.tbStudentScores WHERE fdStudent# = @StudentNum AND fdTestID = @TestID ORDER BY fdAttempt DESC LIMIT 1

    END

    BEGIN TRANSACTION
                  BEGIN
            IF NOT EXISTS (SELECT * FROM dbo.tbStudentScores WHERE fdStudent# = @StudentNum AND fdTestID = @TestID AND fdDateCompleted = @DateCompleted AND fdScore = @Score)

                     INSERT INTO dbo.tbStudentScores 
                                (fdStudent#,
             fdTestID,
             fdAttempt,
             fdDateCompleted,
             fdScore) 
                        VALUES (@StudentNum,
             @TestID,
             @Attempt,
             @DateCompleted,
             @Score) 
        END
                     -- END INSERT INTO dbo.tbStudentScores 

    IF @@error <> 0
        BEGIN
            ROLLBACK TRANSACTION
            RETURN 1
        END

    ELSE
        BEGIN
            COMMIT TRANSACTION
            RETURN 0
        END
END
-- END PROCEDURE [dbo].spRecordStudentScore
GO

Ответы [ 4 ]

1 голос
/ 15 июля 2011

Если вы просто пытаетесь найти номер следующей попытки, вам не нужно ничего особенного - вот самый простой sql для него:

ОБЪЯВИТЬ @Attempt int;

SELECT 
    @Attempt = isnull(max(fdAttempt),0)
FROM 
    dbo.tbStudentScores 
WHERE 
    fdStudent# = @StudentNum 
    AND fdTestID = @TestID

Вы можете добавить +1 к нему перед следующей вставкой - либо:

SET @Attempt = @Attempt + 1

ИЛИ в SELECT, просто +1 там

SELECT 
        @Attempt = isnull(max(fdAttempt),0) + 1
...
0 голосов
/ 15 июля 2011

Попробуйте это

SET @Attempt = SELECT TOP 1 fdAttempt FROM dbo.tbStudentScores WHERE fdStudent# = @StudentNum AND fdTestID = @TestID ORDER BY fdAttempt DESC)

0 голосов
/ 15 июля 2011

Пожалуйста, смотрите мои комментарии ниже:

CREATE PROCEDURE [dbo].spRecordStudentScore
     @StudentNum            BIGINT,
     @TestID               BIGINT,
     @DateCompleted     DATETIME,
     @Score        FLOAT

Я вижу, что @Score определяется как FLOAT ... что будет приблизительным значением.Вы уверены, что не хотите использовать вместо этого DECIMAL тип?

Кроме того, BIGINT кажется довольно большим для TestID или StudentNum (если StudentNum действительно не должно бытьVARCHAR) ... вы уверены, что INT будет недостаточно?

AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @Attempt int;

    SET @Attempt = 1;

    BEGIN
    IF NOT EXISTS (SELECT * FROM dbo.tbStudentScores WHERE fdStudent# = @StudentNum AND fdTestID = @TestID AND fdAttempt = @Attempt)
        SET @Attempt = 1;
    ELSE 
        SELECT @Attempt = fdAttempt FROM dbo.tbStudentScores WHERE fdStudent# = @StudentNum AND fdTestID = @TestID ORDER BY fdAttempt DESC LIMIT 1

    END

Вместо LIMIT 1 вы можете сделать SELECT TOP 1 @Attempt = fdAttempt ...

    BEGIN TRANSACTION
                  BEGIN
            IF NOT EXISTS (SELECT * FROM dbo.tbStudentScores WHERE fdStudent# = @StudentNum AND fdTestID = @TestID AND fdDateCompleted = @DateCompleted AND fdScore = @Score)

Запись может фактически проникнуть сюда между проверкой, если она существует, и до ее вставки ... если вам нужно предотвратить это, вам нужно будет использовать сериализуемое чтение ... возможно, с исключительной блокировкой чтения.а также, чтобы предотвратить тупик.Или лучше было бы убедиться, что у вас есть соответствующие уникальные ограничения для таблицы.

                     INSERT INTO dbo.tbStudentScores 
                                (fdStudent#,
             fdTestID,
             fdAttempt,
             fdDateCompleted,
             fdScore) 
                        VALUES (@StudentNum,
             @TestID,
             @Attempt,
             @DateCompleted,
             @Score) 
        END
                     -- END INSERT INTO dbo.tbStudentScores 

Какую версию MS SQL Server вы используете?Если это 2005 или более поздняя версия, вы должны проверить TRY CATCH блоков для обработки ошибок.

    IF @@error <> 0
        BEGIN
            ROLLBACK TRANSACTION
            RETURN 1
        END

    ELSE
        BEGIN
            COMMIT TRANSACTION
            RETURN 0
        END
END
-- END PROCEDURE [dbo].spRecordStudentScore
GO
0 голосов
/ 15 июля 2011

Заменить эту строку

SELECT @Attempt = fdAttempt FROM dbo.tbStudentScores WHERE fdStudent# = @StudentNum AND fdTestID = @TestID ORDER BY fdAttempt DESC LIMIT 1

с этим

SELECT TOP 1 @Attempt = fdAttempt FROM dbo.tbStudentScores WHERE fdStudent# = @StudentNum AND fdTestID = @TestID ORDER BY fdAttempt DESC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...