Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft Access Новый топик    Ответить
Топик располагается на нескольких страницах: Ctrl  назад   1 2 3 4 5 [6] 7 8   вперед  Ctrl      все
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Владимир Саныч
Member

Откуда: Израиль (причем это 1 человек, а не 2 => прошу на ты)
Сообщений: 40414
Для полноты картины:

create table xx (id counter)

Эта команда создает таблицу со счетчиком. Странно, что до сих пор в этом топике она не появилась.
3 мар 04, 21:47    [562473]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Владимир Саныч
Member

Откуда: Израиль (причем это 1 человек, а не 2 => прошу на ты)
Сообщений: 40414
Получение последнего значения счетчика для adp:

SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY]

Спасибо Темному!
16 апр 04, 14:44    [633102]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Темный
Member

Откуда:
Сообщений: 11941
Вах! Прыятно, да!
16 апр 04, 15:12    [633202]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Артист
Member

Откуда: Россия
Сообщений: 6224
маленькое уточнение
SELECT @блабла = SCOPE_IDENTITY
в ХП вернет null
пользоваться параметром вывода
RETURN SCOPE_IDENTITY
19 апр 04, 23:44    [636951]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Odess
Member

Откуда: Одесса, Украина
Сообщений: 6065
Странно, у меня "SELECT SCOPE_IDENTITY() as maxID" возвращает не NULL - а реальное значение счетчика. A2002, SQL 2000.
19 апр 04, 23:50    [636954]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Артист
Member

Откуда: Россия
Сообщений: 6224
у меня null
ado.net + msde
щас в bol залезу
19 апр 04, 23:53    [636955]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Владимир Саныч
Member

Откуда: Израиль (причем это 1 человек, а не 2 => прошу на ты)
Сообщений: 40414
Мужики, вы говорите о разных командах.
19 апр 04, 23:57    [636958]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Odess
Member

Откуда: Одесса, Украина
Сообщений: 6065
У меня выдавал NULL когда я добавлял запись через .ADDNEW, пришлось переделать через "insert into ..." - тогда все заработало. Почему не работает в первом случае - лень было разбираться...
19 апр 04, 23:59    [636959]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Odess
Member

Откуда: Одесса, Украина
Сообщений: 6065
2 ВС
Мы говорим об SCOPE_IDENTITY() - а как ее возвращать дело второе ИМХО.
20 апр 04, 00:02    [636960]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Владимир Саныч
Member

Откуда: Израиль (причем это 1 человек, а не 2 => прошу на ты)
Сообщений: 40414
Вы говорите о том, что через
SELECT SCOPE_IDENTITY() as maxID
и
RETURN SCOPE_IDENTITY
оно работает, а через
SELECT @блабла = SCOPE_IDENTITY
нет. Вы тут спорите о чем-то, а спорить не о чем.
20 апр 04, 00:08    [636962]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Артист
Member

Откуда: Россия
Сообщений: 6224
BOL дома нету,
прошолся гуглом и нашел тока на клиппере кто то столкнулся тынц
и Павла 2001 года тынц но у меня не то, я через command, завтра на ado.net форуме задам
ALTER PROCEDURE dbo.spNewSD2


....

AS
INSERT INTO tSdelka ( dogovor, ddogovor, ....)
VALUES (@ndogovor, @ddogovor, ...)

SELECT @idsd = SCOPE_IDENTITY()
...
20 апр 04, 00:15    [636966]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Артист
Member

Откуда: Россия
Сообщений: 6224
тьфу, прошу прошения...
подмахнуф вместо @@identity незаметил :)
все ухожу спать, спасибо!
20 апр 04, 00:18    [636968]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Odess
Member

Откуда: Одесса, Украина
Сообщений: 6065
2 Артист
Кларион и Клиппер абсолютно разные вещи ;-)
Я аж прыгул по ссылке - думаю неуж то Клиппер с эскюлем стыковали? ;-)))
Я на Клиппере много задач решил в свое времяю Он даже лицензионный был у меня...
20 апр 04, 00:21    [636969]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Артист
Member

Откуда: Россия
Сообщений: 6224
вернулся из кровати
позвольте а кроме как в параметре я тогда несмог бы использовать SCOPE_IDENTITY ?

Кларион и Клиппер абсолютно разные вещи ;-)
ну да кларион магнитолы есть такие
20 апр 04, 00:27    [636970]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Артист
Member

Откуда: Россия
Сообщений: 6224
сам же и отвечаю, после INSERT писать SCOPE_IDENTITY в переменную
и юзать - иначе SCOPE_IDENTITY будет null
https://www.sql.ru/forum/actualthread.aspx?bid=1&tid=87320
опять с вашими идентитями не выспалюсь ...
20 апр 04, 00:47    [636978]     Ответить | Цитировать Сообщить модератору
 Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
Владимир Саныч
Member

Откуда: Израиль (причем это 1 человек, а не 2 => прошу на ты)
Сообщений: 40414
Самый-самый последний вариант.

Вопросы.

Q1: Как создать свой счетчик (чтобы поле было не типа счетчик)?

Q2: Как заставить счетчик начать выдавать значения начиная с некоторой заданной величины?

Q3: Может ли поле счетчика содержать повторяющиеся значения?

Q4: В таблице есть счетчик, но его значения идут не подряд, несколько чисел в середине отсутствуют. Как перезаполнить поле, чтобы дырок не было? (Другой вариант вопроса. Счетчик показывает, что последняя запись в моей таблице имеет номер N, а реально записей меньше. Почему счетчик неправильно считает количество записей в таблице? Что это - баг или фича?)

Q5: Как сымитировать счетчик в отчете?

Q6: Как сымитировать счетчик в запросе на добавление?

Q7: Как сымитировать счетчик в обычном запросе либо ленточной форме?

Q8: Как получить значение счетчика только что добавленной записи?

Q9: Как создать одним запросом таблицу со счетчиком?

Вопросы с ответами.

Q1: Как создать свой счетчик (чтобы поле было не типа счетчик)?

A: Надо написать функцию, к которой обращаться либо в DefaultValue контрола (к сожалению, DefaultValue поля в таблице допускает только ограниченный набор стандартных функций), либо в программе, которая добавляет запись через рекордсет, либо в запросе на добавление. Ниже приведено несколько вариантов такой функции. Особое внимание надо уделить обработчику ошибок.

Вариант 1:

Nz(DMax(...),0)+1

Так можно нумеровать записи даже внутри группы, а не только насквозь через всю таблицу. Для этого надо правильно задать параметры DMax.

Правда, надо отдельно позаботиться о ситуации, когда два юзера обратятся к этому "генератору счетчиков" одновременно. На этот случай надо написать обработчик ошибок.

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

Function Cou() As Long


Dim ws As Workspace, db As Database
Dim rsCounter As Recordset

On Error GoTo errCou
Set ws = DBEngine(0)
Set db = CurrentDb
1
ws.BeginTrans
2
Set rsCounter = db.OpenRecordset("select * from tabCounter")
3
rsCounter.AddNew
Cou = rsCounter!nCounter
'Close without update!'
rsCounter.Close
4
ws.CommitTrans
5
Exit Function

errCou:
Select Case Erl
Case 3
rsCounter.Close
Set rsCounter = Nothing
ws.Rollback
DBEngine.Idle DB_FREELOCKS
Resume 1
Case 2, 4
ws.Rollback
DBEngine.Idle DB_FREELOCKS
Resume 1
Case Else
Resume Next
End Select

End Function

Подвариант: все-таки делать rsCounter.Update, тогда по виду этой таблицы будет сразу ясно, какое значение было выдано последним. Правда, в этом случае файл станет расти.

Еще подвариант: держать в этой таблице одну запись, в которой находится очередное значение счетчика, и вместо AddNew делать Edit и rsCounter!nCounter=rsCounter!nCounter+1, а потом соответственно Update.

Вариант 3 (от Гетца): Держим в отдельной таблице очередное значение счетчика и каждый раз увеличиваем его на 1. Таблица блокируется на момент чтения и увеличения счетчика, а все, кто в нее будут в это время стучаться, спокойно ждут (см. обработчик ошибок adhGetNextAutoNumber_Err) освобождения таблицы.

Function adhGetNextAutoNumber(ByVal strTableName As String) As Long


On Error GoTo adhGetNextAutoNumber_Err

Dim wrk As dao.Workspace
Dim db As dao.Database
Dim rstAutoNum As dao.Recordset
Dim lngW As Long
Dim lngX As Long
Dim intRetryCount As Integer

Randomize
DoCmd.Hourglass True
intRetryCount = 0

Set wrk = dao.DBEngine.Workspaces(0)
Set db = wrk.OpenDatabase(adhCurrentDBPath() & adhcAutoNumDb, False)
Set rstAutoNum = db.OpenRecordset(strTableName & "_ID", dbOpenTable, dbDenyRead)

rstAutoNum.MoveFirst
rstAutoNum.Edit
rstAutoNum!NextAutoNumber = rstAutoNum!NextAutoNumber + 1
rstAutoNum.Update

adhGetNextAutoNumber = lngNextAutoNum

adhGetNextAutoNumber_Exit:
DoCmd.Hourglass False
On Error Resume Next
rstAutoNum.Close
Set rstAutoNum = Nothing
db.Close
Set db = Nothing
wrk.Close
Set wrk = Nothing
Exit Function

adhGetNextAutoNumber_Err:
Select Case Err.Number
Case adhcErrRI, adhcLockErrCantUpdate2, adhcLockErrTableInUse
intRetryCount = intRetryCount + 1
If intRetryCount > adhcLockRetries Then
adhGetNextAutoNumber = -1
Resume adhGetNextAutoNumber_Exit
Else
dao.DBEngine.Idle
lngW = intRetryCount ^ 2 * _
Int((adhcLockUBound - adhcLockLBound + 1) * Rnd() + adhcLockLBound)
For lngW = 1 To lngW
DoEvents
Next lngW
Resume
End If
Case Else
MsgBox "Error " & Err.Number & ": " & Err.Description, _
vbOKOnly + vbCritical, "adhGetNextAutoNumber"
adhGetNextAutoNumber = -1
Resume adhGetNextAutoNumber_Exit
End Select

End Function

Q2: Как заставить счетчик начать выдавать значения начиная с некоторой заданной величины?

A1: Добавить в таблицу со счетчиком при помощи инсерта запись, в которой полю счетчика дается значение на 1 меньше, чем надо. Потом удалить эту запись. Способ работает только при условии, что этот счетчик этого или большего значения еще не выдавал. (Если таким образом дать счетчику отрицательное значение, то он начнет выдавать отрицательные значения, несмотря на то что уже выдавал значения, большие их. Играя на этом, можно добиться, чтобы счетчик выдавал любые значения, в т.ч. и те, которые уже были.)

A2: Сжать базу, в которой сидит таблица со счетчиком. Счетчик будет выдавать значения начиная с наибольшего из существующих +1. В некоторых версиях Аксесса это работает только при условии, что таблица со счетчиком пуста (и тогда счетчик начнет выдавать значения с 1).

A3: Начиная с Аксесса 2000, можно запустить запрос наподобие такого:

alter table Таблица1 alter column ПолеСчетчик counter(1,1)

Q3: Может ли поле счетчика содержать повторяющиеся значения?

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

Q4: В таблице есть счетчик, но его значения идут не подряд, несколько чисел в середине отсутствуют. Как перезаполнить поле, чтобы дырок не было? (Другой вариант вопроса. Счетчик показывает, что последняя запись в моей таблице имеет номер N, а реально записей меньше. Почему счетчик неправильно считает количество записей в таблице? Что это - баг или фича?)

A: Это нормальная ситуация. Если возникла необходимость, чтобы значения счетчика шли подряд, значит база была спроектирована неверно. Поле счетчика должно служить только для однозначной идентификации записей (и, возможно, порядка их занесения), юзер не должен видеть его значений, а если и увидит, то не должен возражать против тех значений, которые есть. Счетчик не служит для подсчета записей.

Q5: Как сымитировать счетчик в отчете?

A: Заводим текстбокс и задаем ему свойства:

ControlSource = "=1"

RunningSum = True

Q6: Как сымитировать счетчик в запросе на добавление?

A: Пишем функцию примерно такого вида:

Function MyFun(varDummy As Variant, Optional iStartValue As Variant) As Long

Static n As Long
If IsMissing(iStartValue) Then
MyFun = n
n = n + 1
Else
n = iStartValue
MyFun = True
End If
End Function

В запросе обращаемся к ней дважды:

  • в части WHERE - с параметрами (чтоугодно,N), где N равно нужному начальному значению счетчика;
  • в части SELECT - в качестве первого параметра передавать любое поле из таблицы, второй параметр не указывать.

    Внимание: упрощать этот код, удаляя из него параметр, передаваемый в части SELECT, - нельзя. Без параметра функция будет вызвана только один раз, а не в каждой записи заново.

    Q7: Как сымитировать счетчик в обычном запросе либо ленточной форме?

    A1:
    SELECT (Select Sum(1) From t AS p Where p.f<=p1.f), p1.f
    FROM t AS p1
    ORDER BY p1.f;

    A2:
    SELECT DCount("f", "t","f<=" & CStr(f)), f
    FROM t
    ORDER BY f;

    Примечание 1. Поле f обязано быть уникальным.

    Примечание 2. Способ 1 быстрее работает, но является необновляемым.

    Q8: Как получить значение счетчика только что добавленной записи?

    A1: Если запись добавляется через рекордсет, то так:

    rs.AddNew
    
    переменная = rs!полесчетчика
    ...
    rs.Update

    A2: Более широкий круг применимости у такого способа:

    Dim rs As ADODB.Recordset 
    
    Set rs = New ADODB.Recordset
    CurrentProject.Connection.Execute "INSERT ..."
    rs.Open "SELECT @@identity as cou", CurrentProject.Connection
    переменная = rs!cou
    rs.Close

    Однако и этот способ имеет ограничения, а именно:
  • работает только через ADO, только в Jet 4 и позже, и только с базами формата Аксесса 2000 и позже;
  • возвращает значение только из записи, добавленной программно, но не через юзер-интерфейс.

    A3: Для adp годится такая модификация того же способа:

    SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY]

    Q9: Как создать одним запросом таблицу со счетчиком?

    A: create table xx (id counter)
  • 30 апр 04, 16:32    [660189]     Ответить | Цитировать Сообщить модератору
     Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
    Владимир Саныч
    Member

    Откуда: Израиль (причем это 1 человек, а не 2 => прошу на ты)
    Сообщений: 40414
    Опубликовано!
    30 апр 04, 16:47    [660232]     Ответить | Цитировать Сообщить модератору
     Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
    sposad
    Member

    Откуда:
    Сообщений: 62187
    Уважаемые, прошу сразу не бить, но позвольте спросить - насколько порочна идея, касающаяся SQL-adp. Принцип состоит в использовании id таблицы SQL server. Т.е. составлять уникальный (???) номер строки, добавляя по 1 к id.
    Добавляя не арифметически, а строчно. Просветите пожалуйста, насколько будет уникален такой номер.
    30 апр 04, 16:54    [660256]     Ответить | Цитировать Сообщить модератору
     Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
    Владимир Саныч
    Member

    Откуда: Израиль (причем это 1 человек, а не 2 => прошу на ты)
    Сообщений: 40414
    Он не будет уникален, потому что два юзера могут одновременно создать одинаковое значение.

    А что значит строчно? Типа, если было
    11111111111111111111111111111
    то добавить 1 и получить
    111111111111111111111111111111
    ?
    30 апр 04, 16:56    [660265]     Ответить | Цитировать Сообщить модератору
     Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
    sposad
    Member

    Откуда:
    Сообщений: 62187
    ну да
    30 апр 04, 16:58    [660271]     Ответить | Цитировать Сообщить модератору
     Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
    Владимир Саныч
    Member

    Откуда: Израиль (причем это 1 человек, а не 2 => прошу на ты)
    Сообщений: 40414
    Но тогда он не только не будет уникальным, но и поле придется под него заводить бешеного размера, и все равно оно быстро кончится. Зачем делать плохо, если можно делать хорошо?
    30 апр 04, 17:01    [660279]     Ответить | Цитировать Сообщить модератору
     Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
    sposad
    Member

    Откуда:
    Сообщений: 62187
    Сан Саныч, прошу прошения за неточность, я имел ввиду следующее

    ID - 1234
    1 строка - 12341
    2 строка 12342
    3 строка 12343
    4 строка 12344
    30 апр 04, 17:04    [660293]     Ответить | Цитировать Сообщить модератору
     Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
    sposad
    Member

    Откуда:
    Сообщений: 62187
    Владимир Саныч - я чёкнулся - простите
    30 апр 04, 17:06    [660303]     Ответить | Цитировать Сообщить модератору
     Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
    Владимир Саныч
    Member

    Откуда: Израиль (причем это 1 человек, а не 2 => прошу на ты)
    Сообщений: 40414
    А если будет 12349, то дальше 123410? Или 123491?
    30 апр 04, 17:07    [660308]     Ответить | Цитировать Сообщить модератору
     Re: FAQ. Что мы знаем про каунтеры (aka счетчики)  [new]
    sposad
    Member

    Откуда:
    Сообщений: 62187
    Не конец дня и праздник впереди - убить меня мало
    30 апр 04, 17:08    [660309]     Ответить | Цитировать Сообщить модератору
    Топик располагается на нескольких страницах: Ctrl  назад   1 2 3 4 5 [6] 7 8   вперед  Ctrl      все
    Все форумы / Microsoft Access Ответить