powered by simpleCommunicator - 2.0.41     © 2025 Programmizd 02
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / FAQ. Что мы знаем про каунтеры (aka счетчики)
25 сообщений из 176, страница 2 из 8
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32223967
Фотография Geo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...между MoveFirst и Delete ...
Не понял сразу, прошу прощения.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32223975
Фотография Senin Viktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
у кого Гетц под рукой - скинте сюда его пример работы с собственным счетчиком.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32224020
Хам трамвайный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
т.2 стр.87
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32225818
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Новая версия. Изменения выделены болдом.

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

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

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

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

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

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 tab Counter")
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

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

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

A2: Сжать базу, в которой сидит таблица со счетчиком. Счетчик будет выдавать значения начиная с наибольшего из существующих +1.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32227450
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Если у кого есть т.2 стр.87, шепните, плз, о чем там...
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32227466
Фотография Senin Viktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шепчу:)
Правда без Гетцевых комментариев

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
Option Compare Database
Option Explicit

' From Access 2000 Developer's Handbook, Volume II
' by Litwin, Getz, and Gilbert. (Sybex)
' Copyright  1999 . All rights reserved.

' Database storing autonumber values
Const adhcAutoNumDb = "Ch02Auto.Mdb"

' Number of lock retry attempts
Const adhcLockRetries =  5 
' Lower bound of range of retry wait
Const adhcLockLBound = 2
' Upper bound of range of retry wait
Const adhcLockUBound =  10 

'Error constants
Const adhcErrRI = 3000
Const adhcLockErrCantUpdate2 = 3260
Const adhcLockErrTableInUse = 3262

Private Function adhCurrentDBPath() As String
    
    ' Return just the path of the current database,
    ' including the trailing backslash.
    
    ' From Access  2000  Developer's Handbook, Volume II
    ' by Litwin, Getz, and Gilbert (Sybex)
    ' Copyright 1999.  All rights reserved.
    
    ' NOTE: This is only useful if you're using DAO.
    ' If you're using ADO, use the CurrentProject.Path
    ' property instead.
    
    On Error GoTo HandleErrors
    
    Dim intPos As Integer
    Dim strFullPath As String
    
    strFullPath = CurrentDb.Name
    ' Find the last "\" in the file name.
    intPos = InStrRev(strFullPath, "\")
    
    ' Given the position of the final  "\" ,
    ' pull of the path portion.
    If intPos > 0 Then
        adhCurrentDBPath = Left$(strFullPath, intPos)
    Else
        adhCurrentDBPath = strFullPath
    End If
    
ExitHere:
    Exit Function
    
HandleErrors:
    Select Case Err.Number
        Case Else
            Err.Raise Err.Number, Err.Source, _
             Err.Description, _
             Err.HelpFile, Err.HelpContext
    End Select
    Resume ExitHere
End Function

Function adhAssignID(frm As Form, ByVal _
 strTableName As String, _
 ByVal strAutoNumField As String) As Variant

    ' Called from BeforeInsert event of a form to assign
    ' a new custom autonumber value for a field.
    ' Removes any record that cannot be saved.
    '
    ' From Access  2000  Developer's Handbook, Volume II
    ' by Litwin, Getz, and Gilbert. (Sybex)
    ' Copyright 1999. All rights reserved.
    '
    ' In:
    '    frm: form object variable that points to the
    '     currently opened form.
    '    strTableName: the name of the table for which
    '     the autonumber is to be retrieved.
    '    strAutoNumField: the name of the Long Integer
    '     field in strTableName that requires the new
    '     autonumber value.
    ' Out:
    '     Return value: None
    ' Example:
    '     varReturn = adhAssignID(Me,  "tblMenu" ,  "ID" )

    On Error GoTo adhAssignID_Err

    Dim lngNewID As Long

    lngNewID = adhGetNextAutoNumber(strTableName)
    Debug.Print lngNewID
    If lngNewID <> - 1  Then
        frm(strAutoNumField) = lngNewID
    Else
        MsgBox  "Can't Add Record; autonumber " & _
        "Not Available", vbOKOnly + vbCritical, _
        "Error Saving Record"
        frm.Undo
    End If

adhAssignID_Exit:
    Exit Function

adhAssignID_Err:
    frm.Undo
    MsgBox "Error " & Err.Number & ": " & Err.Description, _
     vbOKOnly + vbCritical, "adhAssignID"
    Resume adhAssignID_Exit

End Function

Function adhGetNextAutoNumber(ByVal strTableName _
 As String) As Long
    
    ' Returns the next custom autonumber value for a
    ' particular table. Autonumbers are stored in the
    ' database adhcAutoNumDb in tables with _ID appended
    ' for which they supply autonumbers.
    ' Returns -1  if a valid autonumber value cannot be
    ' retrieved due to locking problems.
    '
    ' From Access 2000 Developer's Handbook, Volume II
    ' by Litwin, Getz, and Gilbert. (Sybex)
    ' Copyright  1999 . All rights reserved.
    '
    ' In:
    '    strTableName: the name of the table for which the
    '     autonumber is to be retrieved.
    ' Out:
    '     Return value: A Long containing the new
    '      autonumber value, or -1 if the routine couldn't
    '      provide a autonumber value.
    ' Example:
    '     lngNewID = adhGetNextAutoNumber("tblMenu")

    On Error GoTo adhGetNextAutoNumber_Err

    Dim wrk As dao.Workspace
    Dim db As dao.Database
    Dim rstAutoNum As dao.Recordset
    Dim lngNextAutoNum As Long
    Dim lngW As Long
    Dim lngX As Long
    Dim intRetryCount As Integer
    
    Randomize
    DoCmd.Hourglass True
    intRetryCount = 0

    ' Open a recordset on the appropriate table in the
    ' autonumbers database denying all reads to others
    ' while it is open
    Set wrk = dao.DBEngine.Workspaces( 0 )
    Set db = wrk.OpenDatabase(adhCurrentDBPath() & _
     adhcAutoNumDb, False)
    Set rstAutoNum = db.OpenRecordset(strTableName _
     & "_ID ", dbOpenTable, dbDenyRead)

    ' Increment and return the autonumber value
    rstAutoNum.MoveFirst
    rstAutoNum.Edit
        lngNextAutoNum = rstAutoNum![NextAutoNumber]
        rstAutoNum![NextAutoNumber] = lngNextAutoNum + 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
        ' Table locked by another user
        intRetryCount = intRetryCount + 1 
        ' Tried too many times, give up
        If intRetryCount > adhcLockRetries Then
            adhGetNextAutoNumber = -1
            Resume adhGetNextAutoNumber_Exit
        Else
            ' Let Windows and the Jet Engine catch up
            dao.DBEngine.Idle
            ' Space out the retries based on a number
            ' that increases by the number of retries
            ' and a random number
            lngW = intRetryCount ^ 2 * _
             Int((adhcLockUBound - adhcLockLBound + 1) _
              * Rnd() + adhcLockLBound)
            ' Waste time, but let Windows
            ' multitask during this dead time.
            For lngW = 1 To lngW
                DoEvents
            Next lngW
            Resume
        End If
        Case Else
            ' Unexpected error
            MsgBox "Error  " & Err.Number & " :  " _
             & Err.Description, _
             vbOKOnly + vbCritical, " adhGetNextAutoNumber"
            adhGetNextAutoNumber = - 1 
            Resume adhGetNextAutoNumber_Exit
    End Select

End Function


...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32227519
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Виктору много енотов!

Я так понимаю, что главное здесь вот что:

Код: plaintext
1.
2.
3.
    rstAutoNum.Edit
        lngNextAutoNum = rstAutoNum![NextAutoNumber]
        rstAutoNum![NextAutoNumber] = lngNextAutoNum +  1 
    rstAutoNum.Update


И словами это описывается так: держим в отдельной таблице очередное значение счетчика и каждый раз увеличиваем его на 1.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32227523
Фотография Senin Viktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Главное: что таблица блокируется на момент чтения и увеличения счетчика, а все кто в нее будут в это время стучаться спокойно ждут (см. обработчик ошибок adhGetNextAutoNumber_Err) освобождения таблицы.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32227528
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
ОК, да, таблица открывается с dbDenyRead.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32227545
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Кстати, похоже, что там баг. Вот две строки, которые идут подряд:

Код: plaintext
1.
        lngNextAutoNum = rstAutoNum![NextAutoNumber]
        rstAutoNum![NextAutoNumber] = lngNextAutoNum +  1 


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

А если бы автор этого кода не выпендривался и написал как человек

Код: plaintext
        rstAutoNum![NextAutoNumber] = rstAutoNum![NextAutoNumber] +  1 


то этого эффекта бы не было.

Другое дело, что на этой строке никогда эррора не будет, но все же, все же, все же...
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32284056
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
К последнему абзацу - новая версия.

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

Geo, тебе спасибо за подсказку.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32284359
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
К тому же вопросу, ответу A1 еще одно примечание:

Если таким образом дать счетчику отрицательное значение, то он начнет выдавать отрицательные значения, несмотря на то что уже выдавал значения, большие их.

И кроме того:

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

A: В принципе да. Этого несложно достичь, меняя состояние счетчика описанными способами. Однако если при этом возникнут нарушения ключа (вообще говоря, поле счетчика можно и не делать ключевым, но обычно все-таки принято делать), то записи просто не смогут добавляться. Каждая неудачная попытка добавить запись будет увеличивать значение счетчика на 1. Когда зона существующих значений будет пройдена, то записи опять смогут добавляться.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32284509
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если таким образом дать счетчику отрицательное значение
Саныч, а почему именно отрицательное? Задаешь любое, и счетчик начинает плясать именно от него. Несмотря на то, что уже были значения большие их.
Кстати, по моему это справедливо только для 97-го. В 2002-м у меня выдавалось как раз Max+1. Очередная загадка от MS.

Может ли поле счетчика содержать повторяющиеся значения?
Если нет уникального индекса - то очень даже может. Причем как в случае шаманства (ручная установка значения), так и в ходе нормальной многопользовательской работы.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32284567
Фотография fedd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
что такое faq - часто задаваемые вопросы.\r
\r
нужно дать ответ на вопрос - "что такое счетыик, зачем он" и "почему счетчик не заполняет дырки в последовательности значений" и сделать небольшой экскурс в теорию о "суррогатных ключах" типа этого
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32284904
Фотография Лох Позорный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что мы НЕ знаем про каунтеры (aka счетчики)

Регулярно, с периодичностью примерно раз в две недели, натыкаюсь на проглючивший первичный ключ в виде счетчика. То туда Null запишется (хотя поле обязательное), то значения задублируются (хотя есть уникальный индекс). Появляется в совершенное разных таблицах, единственное чем они похожи - наличием счетчика. Взглючившие записи - старые, уже существовавшие достаточно долго.
Ни одна таблица с первичным ключом в виде "рукотворного счетчика" (длинное целое) ни каких подобных безобразиях замечена не была.
У кого-нибудь есть мысли по этому поводу?
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32285627
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
> Саныч, а почему именно отрицательное? Задаешь любое, и счетчик начинает плясать именно от него. Несмотря на то, что уже были значения большие их.

Ровно вчера я собственными глазами видел, что это не так. Аксесс 97. Скажем, у счетчика значения до 10. Добавляешь запись с 20, он сам начинает выдавать значения от 21. Потом добавляешь запись с 15, а он нифига.

> То туда Null запишется (хотя поле обязательное), то значения задублируются (хотя есть уникальный индекс).

Похоже, что база накрылась.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32286411
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Поправка от 4 окт 03, 15:10 вроде бы отменяется. :^)
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32286453
Фотография Темный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поправка поправки!!!!
Если удалить все записи и сжать БД, то тогда счетчик сбрасывается. Если удалить только несколько последних и сжать , то тогда облом
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32286477
Фотография Senin Viktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то Темный ты темнишь

Если сжимать именно базу, а не хранилище линков на таблицу, то счетчик сброситься
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32286484
Фотография Темный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все вышесказанное относиться к Access XP SP2.
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32286488
Фотография Темный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Senin Viktor:
А как же это сжать хранилище линков на таблицу
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32286490
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Я проверил в 2000. Действительно облом. :^(
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32286501
Фотография Владимир Саныч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Итак, добавляю способ сбрасывания счетчика (спасибо Хаму):

alter table Таблица1 alter column ПолеСчетчик counter(1,1)
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32286502
Фотография Senin Viktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>А как же это сжать хранилище линков на таблицу

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

==
А что тут смешного было?
...
Рейтинг: 0 / 0
FAQ. Что мы знаем про каунтеры (aka счетчики)
    #32286510
Фотография Темный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я таки знал!
Смешного - ничего. Настроение у меня сегодня хорошее. 3 дня выходных пошли на пользу.

Просто проверку я производил все-таки в базе с таблицами.
...
Рейтинг: 0 / 0
25 сообщений из 176, страница 2 из 8
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / FAQ. Что мы знаем про каунтеры (aka счетчики)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]