2016-03-09 2 views
1

Поэтому у меня есть 1 столКак я могу это сделать в T-SQL?

CREATE TABLE Versions (
    id INT IDENTITY(1,1), 
    title NVARCHAR(100), 
    PRIMARY KEY (id) 
) 

и другая таблица

CREATE TABLE Questions (
    id INT IDENTITY(1,1), 
    subsection_id INT NOT NULL, 
    qtext NVARCHAR(400) NOT NULL, 
    version_id INT NOT NULL, 
    viewtype INT NOT NULL DEFAULT 1, 
    PRIMARY KEY (id), 
    FOREIGN KEY (subsection_id) REFERENCES Subsections(id), 
    FOREIGN KEY (version_id) REFERENCES Versions(id) 
); 

визуальное представление, которое, как

--           Questions 
-- ============================================================================================================================ 
-- id |     qtext            | subsection_id | version_id | viewtype 
-- ============================================================================================================================= 
-- 1 | 'Does Hillary Clinton look good in orange?'      |  1   |  1  |  1 
-- 2 | 'How many prime numbers are there?'        |  1   |  1  |  1 
-- 3 | 'What do I suck at writing SQL?'         |  1   |  1  |  1 
-- 4 | 'Would Jon Skeet beat Mark Zuckerberg in a programming contest?' |  1   |  1  |  1 

Что мне нужно, это процедура, которая и вставляет новую строку к таблице Versions и добавляет в таблицу Questions все ее текущие строки с соответствующим образом увеличивающимся id s и version_id s, равным той, которая была только что создана.

Пример:

Если Versions идет от

id | title 
----------- 
1 | "V1" 
2 | "V2" 

затем Questions идет в

--           Questions 
-- ============================================================================================================================ 
-- id |     qtext            | subsection_id | version_id | viewtype 
-- ============================================================================================================================= 
-- 1 | 'Does Hillary Clinton look good in orange?'      |  1   |  1  |  1 
-- 2 | 'How many prime numbers are there?'        |  1   |  1  |  1 
-- 3 | 'What do I suck at writing SQL?'         |  1   |  1  |  1 
-- 4 | 'Would Jon Skeet beat Mark Zuckerberg in a programming contest?' |  1   |  1  |  1 
-- 5 | 'Does Hillary Clinton look good in orange?'      |  1   |  2  |  1 
-- 6 | 'How many prime numbers are there?'        |  1   |  2  |  1 
-- 7 | 'What do I suck at writing SQL?'         |  1   |  2  |  1 
-- 8 | 'Would Jon Skeet beat Mark Zuckerberg in a programming contest?' |  1   |  2  |  1 

Лучшая попытка с моими ограниченными навыками базы данных:

CREATE PROCEDURE OntoNewVersion 
    @new_title NVARCHAR(100) 
AS 
    INSERT INTO Versions (title) VALUES (@new_title) 
    SET @versid = SCOPE_IDENTITY() 
    SET @qrows = SELECT COUNT(*) FROM Questions; -- this is wrong, I know 
    SET @i = 1; 
    WHILE @i <= @qrows 
     BEGIN 
      SET @thisq = SELECT * FROM Questions WHERE [email protected] 
      INSERT INTO Questions (qtext,subsection_id,version_id,viewtype) VALUES (@thisq.qtext,@thisq.subsection_id,@versid,@thisq.viewtype); 
     END 

Насколько это правильно? Что изменилось? Есть ли лучший способ сделать это?

+0

Это не будет работать. На самом деле вам вообще не нужен цикл. Вы должны посмотреть на использование OUTPUT. https://msdn.microsoft.com/en-us/library/ms177564.aspx –

+0

Пожалуйста, взгляните на мой ответ – DhruvJoshi

+0

Почему вы создаете несколько копий вопросов? Кажется, у вас проблемы с нормализацией. –

ответ

1

Вы можете попробовать ниже запрос

CREATE PROCEDURE OntoNewVersion 
    @new_title NVARCHAR(100) 
AS 
BEGIN 
BEGIN TRY 
    BEGIN TRANSACTION T1 
    DECLARE @versid INT 
    INSERT INTO Versions (title) VALUES (@new_title) 
    SET @versid = SCOPE_IDENTITY() 


    INSERT INTO Questions 
     (qtext,subsection_id,version_id,viewtype) 
    SELECT qtext, subsection_id,@versid,viewtype 
    FROM Questions 
    COMMIT TRANSACTION T1 
END TRY 

BEGIN CATCH 
    IF(@@TRANCOUNT>0) 
    BEGIN 
     ROLLBACK TRANSACTION T1 
    END 
    ;THROW  
END CATCH 
END 
+1

Почему вы рекомендуете использовать MAX (Id) вместо того, что вы разместили? То, что вы разместили, - это правильный способ сделать это. Использование MAX (Id) подвержено условиям гонки и параллелизму. Это не очень хороший способ сделать это. –

+0

Это происходит исключительно из-за несвязанного личного опыта, неудавшаяся транзакция заставляет мое значение идентификации по-прежнему увеличиваться и удерживать ложное значение, которое на самом деле не существует. – DhruvJoshi

+0

Huh ??? SCOPE_IDENTITY вернет последнее значение идентификатора из текущей области. Если вставка завершилась неудачей, значение все равно будет возвращено, но строка не будет вставлена. Способ справиться с этим заключается в том, чтобы положить все это в транзакцию. Таким образом, если вставка в Версии не удалась, вставка в «Вопросы» также будет откатна. –

Смежные вопросы