Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
Добрый день!

Переписываю систему учета с DBF на MS SQL (2005).
В системе ведутся данные по Клиентам. У каждого Клиента может быть несколько Объектов.
Номер Объекта в БД имеет тип char(3).

Объекты могут закрываться, а так же открываться новые. При заведении нового Объекта ему должен быть присвоен следующий уникальный номер.

Например:
Были Объекты (и открытые и закрытые) с номерами

21
25
30
31
32

Следующий номер должен быть 33.

Однако проблема в типе данных! Для Клиентов, у которых исторически все Объекты нумеруются так, что можно привести тип char(3) к integer - все тривиально.
Но есть Клиенты, у которых есть Объекты (очень старые и уже закрытые, но вопрос об их удалении из БД пока не решен), для которых такое преобразование не возможно.

Подскажите пожалуйста, как обойти исключение?
3 сен 09, 10:33    [7611578]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
_Help_me_please_
Подскажите пожалуйста, как обойти исключение?
А какие последствия этого исключения?
Данные теряются?
Ошибка возникает?
3 сен 09, 10:37    [7611620]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74927
Новый номер объекта сделайте int. Старые номера в отдельное поле char.
3 сен 09, 10:38    [7611623]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
Если пробую делать запрос
select
max(cast(object_number as int))
from 
cust_object
where ...

Выдает ошибку вроде:
Conversion failed when converting the varchar value ' 4.' to data type int., т.к. номер содержит точку или букву.
А хотелось бы чтобы запрос обрабатывал только номера, которые приводимы к типу Int.

Т.е. если была последоватьельность:
'1', '2', 'F', '3.' и т.д. - то должен выдать наибольший целочисленный номер, т.е. '2'.
3 сен 09, 10:55    [7611777]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
_Help_me_please_
Если пробую делать запрос
select
max(cast(object_number as int))
from 
cust_object
where ...
Допустим, все данные у Вас "приводимы к int"
Если этот запрос выполнят сразу два клиентских подключения,
то они получат одинаковый максимум и сгенерируют одинаковый "следующий номер"
Я правильно догадался?
3 сен 09, 11:00    [7611815]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
Паганель,

да - но в данном случае это не принципиально. Т.к. номер "предлагается". В принципе оператор может его исправить и на другой.
3 сен 09, 11:04    [7611845]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
Crimean
Member

Откуда:
Сообщений: 13148
+ поле типа int. индекс на него. уникальный, если надо. в нем вести нормальные номера. в старое поле писать что-то типа ltrim( str( новое_поле )). всем щасте. как вариант - таблицу переименовать, сделать +1 поле, сделать пердставление минус это поле со старым именем. максимум - триггера навесить надо будет на вьюву
3 сен 09, 11:06    [7611856]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
-- test data
declare @t table(n char(3))
insert into @t(n)
select '  1' union all
select '  2' union all
select '  F' union all
select ' 3.' 
-- end of test data

set ansi_warnings off
select max(cast(case when n like '[ 1234567890][ 1234567890][ 1234567890]'
                     then n 
                     else null
                 end
                as int)) as result
  from @t
set ansi_warnings on

result
-----------
2

(1 row(s) affected)
но все-таки желательно привести БД в порядок, то есть хранить целое число как целое число
3 сен 09, 11:12    [7611903]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
проходящий.
Guest
_Help_me_please_
Паганель,

да - но в данном случае это не принципиально. Т.к. номер "предлагается". В принципе оператор может его исправить и на другой.
А захочет? И что будет в очень вероятном случае нехотения?
3 сен 09, 11:23    [7612005]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
AeDen
Member

Откуда:
Сообщений: 2
Паганель
-- test data
declare @t table(n char(3))
insert into @t(n)
select '  1' union all
select '  2' union all
select '  F' union all
select ' 3.' 
-- end of test data

set ansi_warnings off
select max(cast(case when n like '[ 1234567890][ 1234567890][ 1234567890]'
                     then n 
                     else null
                 end
                as int)) as result
  from @t
set ansi_warnings on

result
-----------
2

(1 row(s) affected)
но все-таки желательно привести БД в порядок, то есть хранить целое число как целое число


А если добавить
select '1 8' union all?
3 сен 09, 11:57    [7612337]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
Спасибо! Мне вполне хватит что-то вроде того:
select max(cast(object_number as int))
from 
cust_object
where
object_number like '[ 1234567890][ 1234567890][ 1234567890]'

Перед обедом тоже пришла мысля насчет like :)

> А захочет? И что будет в очень вероятном случае нехотения?
В данном случае я отмажусь тем, что бизнес-процесс не позволит спутать карты.
3 сен 09, 11:58    [7612342]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
AeDen, да, про пробел в середине я не подумал
-- test data
declare @t table(n char(3))
insert into @t(n)
select '  1' union all
select ' 2 ' union all
select '  F' union all
select '1 8' union all
select ' 3.' 
-- end of test data

set ansi_warnings off
select max(cast(case when n like '[ 1234567890][ 1234567890][ 1234567890]' and isnumeric(n) = 1
                     then n 
                     else null
                 end
                as int)) as result
  from @t
set ansi_warnings on
3 сен 09, 12:03    [7612386]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
Паганель,

select max(cast(object_number as int))
from 
cust_object
where
object_number like '  [1234567890]'
or
object_number like ' [1234567890][1234567890]'
or
object_number like '[1234567890][1234567890][1234567890]'

ЭВРИКА :)
3 сен 09, 12:07    [7612417]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
или

select max(cast(object_number as int))
from 
cust_object
where
ltrim(retim(object_number)) like '[1234567890]'
or
ltrim(retim(object_number)) like '[1234567890][1234567890]'
or
ltrim(retim(object_number)) like '[1234567890][1234567890][1234567890]'
3 сен 09, 12:08    [7612431]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
retim читать как rtrim
3 сен 09, 12:10    [7612443]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
Хотя


declare @t table(n char(3))
insert into @t(n)
select '  1' union all
select ' 2 ' union all
select '  F' union all
select '1 8' union all
select ' 3.' 
-- end of test data

select cast(max(cast(n as real))+1 as char(3))
from 
@t
where
isnumeric(n)=1

Тоже неплохо
3 сен 09, 12:20    [7612531]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
_Help_me_please_
Тоже неплохо
_Help_me_please_
'1', '2', 'F', '3.' и т.д. - то должен выдать наибольший целочисленный номер, т.е. '2'.
А Ваш последний вариант выдает 4
3 сен 09, 12:26    [7612560]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
Паганель,

ага - остановилась все-таки на варианте с тримом и лайком.
Только плохо будет, когда мы будем выходить за ограничение 3-х знаков.
Но тогда уж в любом случае будет плохо.

Единственный недостаток - процедура не будет предлагать 1, если множество номеров будет пустым.
3 сен 09, 12:29    [7612573]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
_Help_me_please_
когда мы будем выходить за ограничение 3-х знаков.
_Help_me_please_
Номер Объекта в БД имеет тип char(3).
Значит, "за ограничение 3-х знаков" выйти невозможно
3 сен 09, 12:30    [7612585]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
ага :)

а для генерации первого номера - isnull спасет нас
3 сен 09, 12:33    [7612598]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
_Help_me_please_
Единственный недостаток - процедура не будет предлагать 1, если множество номеров будет пустым.

Задача была
_Help_me_please_
выдать наибольший целочисленный номер
если будет выдан NULL, то, наверное, клиентское приложение его должно корректно отработать
3 сен 09, 12:36    [7612613]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
Зачем нагружать этим клиента?
Ведь известно, что нумерация целочисленная, а самое первое целое число, которое я знаю - это 1.
3 сен 09, 12:40    [7612633]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
Uridian
Member

Откуда: Lobnya
Сообщений: 211
declare @t table(n char(3))
insert into @t(n)
select '  1' union all
select ' 2 ' union all
select '  F' union all
select '1 8' union all
select ' 3.' 

select isnull (max (cast (n as int)), 0) + 1
from @t
where rtrim (ltrim (n)) not like '%[^0-9]%'
3 сен 09, 13:14    [7612853]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
_Help_me_please_
Guest
Uridian,

ВСЕ ГЕНИАЛЬНОЕ - ПРОСТО!!!
3 сен 09, 13:37    [7612967]     Ответить | Цитировать Сообщить модератору
 Re: Генерация следующего номера для поля типа char  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
_Help_me_please_
Uridian,

ВСЕ ГЕНИАЛЬНОЕ - ПРОСТО!!!
А что "ГЕНИАЛЬНОЕ"? Uridian ерунду написал.
Как будто условие в WHERE (кстати говоря, не совсем верное) запретит серверу пытаться преобразовать в INT и остальные строки!
Это не говоря о том, что несколько коннектов могут прочитать один и тот же максимум и вычислить одно и то же следующее значение!
Можно посоветовать поискать на форуме многочисленные темы про всё это...
3 сен 09, 13:55    [7613053]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить