Как я могу заставить этот запрос работать? - PullRequest
0 голосов
/ 24 мая 2011

Я вчера отправил вопрос , и по какой-то причине я не могу заставить его работать. Я получил много хороших ответов, но они не соответствуют тому, что мне нужно. По сути, мне нужно выполнить запрос, который будет циклически проходить через всех клиентов, захватывать их Acct_Balance и устанавливать его на 0, но прежде чем установить его на 0, мне нужно добавить запись с этой отрицательной суммой в таблицу AR_Transactions. Так что для реальных чисел, если у клиента есть -200 в поле Acct_Balance в таблице клиентов, тогда мне нужно добавить запись или 200, чтобы довести значение до 0. Это похоже на позицию, равную 0. И наоборот, если у клиента есть 200 в поле Acct_Balance в таблице клиентов, тогда мне нужно добавить запись или -200, чтобы обнулить это значение. Я попробовал несколько вещей. Вот один из примеров, которые я попробовал.

BEGIN TRANSACTION 
INSERT INTO [cresql].[dbo].[AR_Transactions] 
(Trans_ID, DateTime , Dirty, Store_ID, Trans_Type,  Cashier_ID,  CustNum,     Trans_Amount, Prev_Cust_Balance ) 
SELECT  (SELECT MAX(Trans_ID ) + 1 FROM [cresql].[dbo].[AR_Transactions]), DATEADD(MINUTE, -30, Getdate()), 1, 1001, 'C', 100199,     CustNum,     -Acct_Balance,   Acct_Balance 
FROM  [cresql].[dbo].[Customer] 
WHERE Acct_Balance <> 0  
UPDATE [cresql].[dbo].[Customer] SET Acct_Balance = 0 
WHERE Acct_Balance <> 0  
COMMIT TRANSACTION

но я получил эту ошибку

Msg 2627, Level 14, State 1, Line 3
Violation of PRIMARY KEY constraint 'pkAR_Transactions'. Cannot insert duplicate key in object 'dbo.AR_Transactions'.
The statement has been terminated.

Я попытался запустить оператор вставки, и все работает нормально, но с этим запросом он не работает .... Кроме того, первичный ключ pkAR_Transactions явно не является инкрементом, поэтому я делаю этот хак, чтобы получить последнюю запись в этом поле

Вот моя структура БД для двух таблиц ..

Таблица AR_Transaction

column name type allow null 
Trans_ID bigint Unchecked
DateTime datetime Unchecked
Cashier_ID nvarchar(50) Checked
CustNum nvarchar(12) Unchecked
Trans_Type nvarchar(2) Unchecked
Prev_Cust_Balance money Checked
Prev_Inv_Balance money Checked
Trans_Amount money Unchecked
Payment_Method nvarchar(4) Checked
Payment_Info nvarchar(20) Checked
Description nvarchar(38) Checked
Invoice_Number bigint Unchecked
Store_ID nvarchar(10) Unchecked
Dirty bit Unchecked
Station_ID nvarchar(5) Checked
Payment_Type smallint Checked

Таблица клиентов

column name type allow null 
CustNum nvarchar(12) Unchecked
First_Name nvarchar(15) Checked
Last_Name nvarchar(15) Unchecked
Company nvarchar(30) Checked
Address_1 nvarchar(30) Checked
Address_2 nvarchar(30) Checked
City nvarchar(20) Checked
State nvarchar(12) Checked
Zip_Code nvarchar(10) Checked
Phone_1 nvarchar(15) Checked
Phone_2 nvarchar(15) Checked
CC_Type nvarchar(5) Checked
CC_Num nvarchar(50) Checked
CC_Exp nvarchar(8) Checked
Discount_Level nvarchar(1) Unchecked
Discount_Percent real Unchecked
Acct_Open_Date datetime Checked
Acct_Close_Date datetime Checked
Acct_Balance money Checked
Acct_Max_Balance money Checked
Bonus_Plan_Member bit Unchecked
Bonus_Points int Checked
Tax_Exempt bit Unchecked
Member_Exp datetime Checked
Dirty bit Unchecked
Phone_3 nvarchar(15) Checked
Phone_4 nvarchar(15) Checked
EMail nvarchar(50) Checked
County nvarchar(30) Checked
Def_SP nvarchar(10) Checked
CreateDate datetime Checked
Referral nvarchar(20) Checked
Birthday datetime Checked
Last_Birthday_Bonus datetime Checked
Last_Visit datetime Checked
Require_PONum bit Unchecked
Max_Charge_NumDays int Checked
Max_Charge_Amount money Checked
License_Num nvarchar(20) Checked
ID_Last_Checked datetime Checked
Next_Start_Date datetime Checked
Checking_AcctNum nvarchar(20) Checked
PrintNotes bit Unchecked
Loyalty_Plan_ID bigint Checked
Tax_Rate_ID int Checked
Bill_To_Name nvarchar(30) Checked
Contact_1 nvarchar(30) Checked
Contact_2 nvarchar(30) Checked
Terms nvarchar(15) Checked
Resale_Num nvarchar(15) Checked
Last_Coupon datetime Checked
Account_Type smallint Checked
ChargeAtCost bit Checked
Disabled bit Checked
ImagePath nvarchar(255) Checked
License_ExpDate datetime Checked
TaxID nvarchar(20) Checked

Ответы [ 2 ]

2 голосов
/ 24 мая 2011

Запустите это

SELECT  
    (SELECT MAX(Trans_ID ) + 1 
     FROM [cresql].[dbo].[AR_Transactions]), 
     DATEADD(MINUTE, -30, Getdate()), 
     1, 
     1001, 
     'C', 
     100199,
     CustNum,
     -Acct_Balance,
     Acct_Balance  
FROM  [cresql].[dbo].[Customer]  
WHERE Acct_Balance <> 0

Я подозреваю, вы увидите, что все записи получили одинаковый trans_id.В дальнейшем этот хак всегда будет вызывать проблемы с условиями гонки.

Таким образом, реальный вопрос заключается в том, почему не происходит автоинкремент и как получить значение, не вызывая условий гонки?Как другие записи в этой таблице получают значение?Это стороннее программное обеспечение, которое вы не можете изменить?Если есть какой-либо способ исправить это, я бы сделал это в первую очередь.

Поскольку вы говорите, что не можете изменить базу данных, вам все равно нужно выяснить, как она резервирует новые трансиды, чтобы никто другой не попытался использовать тот же самый.Это очень важно.Обычно они резервируют идентификатор, добавляя его в отдельную таблицу идентификаторов и выводя результат этой вставки для использования в остальных своих запросах - если вы не используете тот же метод, вы все испортите.В вашем случае вам нужно будет захватить то же количество идентификаторов, что и количество записей, которые вы собираетесь вставить.Когда у вас есть идентификаторы, вы можете выполнить вставку и обновления.

1 голос
/ 24 мая 2011

Если ответ на любой из приведенных ниже вопросов ДА, не продолжайте.

  • Используется ли таблица AR, когда вы пытаетесь выполнить обновление?
  • Вы работаете над производственной системой для разработки сценария?

Если ответ на любой из приведенных ниже вопросов НЕТ, не продолжайте.

  • Я работаю над системой разработки
  • У меня есть проверенная резервная копия с производства на случай, если что-то пойдет не так.

Я полагаю, что проблема заключается в методе, который вы используете в настоящее время для расчета значения идентификатора AR. Код

(SELECT MAX(Trans_ID ) + 1 FROM [cresql].[dbo].[AR_Transactions])

возвращает единственное значение при запуске скрипта. Одно значение вставляется для каждого клиента с ненулевым балансом. У вас есть возможность создать курсор для таблицы customer, чтобы получить значение customer_id, где баланс не равен нулю. Используйте значение клиента в вашем коде, чтобы добавить строку в таблицу AR, а затем обнулить остаток в таблице клиентов. Перейти к следующему клиенту.

Я не люблю использовать курсоры, поэтому, пожалуйста, не голосуйте за это предложение. ОП не знает, как программа генерирует Id, так что это может быть его единственным шансом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...