Я думаю, что реальная проблема заключается в следующем: действительно ли строки используются только для реализации класса, или они используются где-то еще.
Чтобы быть действительно придирчивым, я бы постарался сохранить интерфейс класса настолько чистым, насколько это возможно, поэтому, если строки имени файла не должны представлять интереса для «внешнего» мира. Я бы скрыл их внутри только в .cpp-файле. И в этом случае я не думаю, что буду беспокоиться о пространстве имен, а просто сохраню «статичность» (т. Е. Внутреннюю по отношению к .cpp-файлу).
попробуйте никогда не зацикливаться, работать с наборами данных.
вы можете вставлять, обновлять, удалять несколько ряды за один раз. здесь в примере вставка нескольких строк:
INSERT INTO YourTable
(col1, col2, col3, col4)
SELECT
cola, colb+Colz, colc, @X
FROM ....
LEFT OUTER JOIN ...
WHERE...
Глядя на цикл, посмотрите, что он внутри него делал. Если он просто вставляет / удаляет / обновляет, перезапишите, чтобы использовать отдельные команды. Если есть IF, посмотрите, могут ли они быть операторами CASE или условиями WHERE при вставке / удалении / обновлении. Если это так, удалите цикл и используйте команды set.
Я взял циклы и заменил их командами, основанными на наборах, и сократил время выполнения с минут до нескольких секунд. Я взял процедуры со многими вложенными циклами и вызовами процедур и сохранил циклы (было невозможно использовать только вставки / удаления / обновления), но я удалил курсор и увидел меньше блокировок / блокировок и значительное повышение производительности. Вот два метода зацикливания, которые лучше, чем циклы курсора ...
если вам нужно зациклить, сделайте что-то вроде этого над набором:
--this looks up each row for every iteration
DECLARE @msg VARCHAR(250)
DECLARE @hostname sysname
--first select of currsor free loop
SELECT @hostname= min(RTRIM(hostname))
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
WHILE @hostname is not null
BEGIN
set @msg='exec master.dbo.xp_cmdshell "net send '
+ RTRIM(@hostname) + ' '
+ 'testing "'
print @msg
--EXEC (@msg)
--next select of cursor free loop
SELECT @hostname= min(RTRIM(hostname))
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
and hostname > @hostname
END
если у вас есть разумный набор элементов (не 100 000), чтобы перебрать вас можно сделать это:
--this will capture each Key to loop over
DECLARE @msg VARCHAR(250)
DECLARE @From int
DECLARE @To int
CREATE TABLE #Rows
(
RowID int not null primary key identity(1,1)
,hostname varchar(100)
)
INSERT INTO #Rows
SELECT DISTINCT hostname
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
SELECT @From=0,@To=@@ROWCOUNT
WHILE @From<@To
BEGIN
SET @From=@From+1
SELECT @msg='exec master.dbo.xp_cmdshell "net send '
+ RTRIM(hostname) + ' '
+ 'testing "'
FROM #Rows WHERE RowID=@From
print @msg
--EXEC (@msg)
END
Я заменил некоторые курсоры на циклы WHILE.
DECLARE @SomeTable TABLE
(
ID int IDENTITY (1, 1) PRIMARY KEY NOT NULL,
SomeNumber int,
SomeText varchar
)
DECLARE @theCount int
DECLARE @theMax int
DECLARE @theNumber int
DECLARE @theText varchar
INSERT INTO @SomeTable (SomeNumber, SomeText)
SELECT Number, Text
FROM PrimaryTable
SET @theCount = 1
SELECT @theMax = COUNT(ID) FROM @SomeTable
WHILE (@theCount <= @theMax)
BEGIN
SET @theNumber = 0
SET @theText = ''
SELECT @theNumber = IsNull(Number, 0), @theText = IsNull(Text, 'nothing')
FROM @SomeTable
WHERE ID = @theCount
-- Do something.
PRINT 'This is ' + @theText + ' from record ' + CAST(@theNumber AS varchar) + '.'
SET @theCount = @theCount + 1
END
PRINT 'Done'
Я написал код, который вычислял промежуточные итоги для финансовых данных, относящихся к данному году. В каждом квартале мне приходилось прибавлять значение текущего квартала к промежуточной сумме при соответствующей обработке NULL, чтобы промежуточная сумма за предыдущий квартал переносилась, когда значение для текущего квартала было NULL.
Первоначально я это делал. это с помощью курсора, и с функциональной точки зрения это соответствовало бизнес-требованиям. С технической точки зрения это оказалось препятствием, потому что по мере увеличения объема данных код занимал экспоненциально больше времени. Решением было заменить курсор на коррелированный подзапрос, который отвечал функциональным требованиям и устранил любые проблемы с производительностью.
Надеюсь, это поможет,
Билл
Что ж, часто разработчик приложений, привыкший к процедурному программированию, по привычке пытается делать все процедурно, даже в SQL.
Чаще всего подойдет SELECT с правильными параметрами - или, может быть, вы имеете дело с оператором UPDATE.
Суть в том, что вам нужно начать думать в виде операций над наборами и сообщать своей СУБД, что вы хотите сделано - не как сделать это шаг за шагом.
Трудно дать единственный, "правильный" ответ на этот вопрос ... вам почти придется показать это на конкретном примере.
Marc