Dimdim SoftWare
Мастерская Dr.dimdim
ГлавнаяПоискНаписать письмо
ГлавнаяМоделированиеПроектированиеТЗРазработкаИнтерфейсСтатьиСсылкиАвтор
Главная > ЧаВО

FAQ: Разработка на MS SQL Server

Автор: НПО "Компьютер", http://www.comp.udmnet.ru/

Вопрос:
Как преобразовать число в строку так, чтобы всегда, независимо от точности числа, отображалось нужное количество знаков после запятой (конкретно - 2)?

Ответ:
Нужно использовать конструкцию вида:
convert(varchar, convert(decimal(<Число знаков>, <Число знаков после запятой>), <Выражение>))
где <Выражение> - это преобразуемое выражение (поле, число и т.п.)
<Число знаков> - общее число знаков в числе (например, 18).
<Число знаков после запятой> - число знаков после запятой (например, 2)


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

Ответ:
Это особенность MS SQL - сервера. Для получения имени приложения надо использовать функции ltrim() и rtrim() при вызове App_Name() или чтении имени приложения из master..sysprocesses.
Типовым решением является:
declare @AppName varchar(128)
select @AppName=rtrim(ltrim(sysp.program_name))
    from master..sysprocesses sysp
   where sysp.spid=@@SPID
И дальше по тексту нужно использовать переменную @AppName:
select @AppName


Вопрос:
Как узнать длину текстового (text) или image- поля?

Ответ:
Нужно использовать функцию DATALENGTH, например:
select datalength(Tekst)
    from MBText


Вопрос:
Всегда ли запрос вида select ... from Table where isnull(Table.Field, getdate())>=getdate(), будет работать правильно при значениях Table.Field равных null? Т.е. возможны ли случаи, когда значения, полученные функциями getdate(), не будут совпадать?

Ответ:
Такой запрос будет работать правильно. Значения будут совпадать, т.к. getdate() берет дату один раз, до начала запроса.


Вопрос:
Есть сложный запрос в котором выполняется только одна из его частей. Выполняемая часть определяется по значению переменной. Пример запроса:
   …
   if @SrcObj='Д'
   begin
      select @RecCount=(@RecCount+count(*)) from MBDoc where NZ = @SrcRecID
      select @RecCount=(@RecCount+count(*)) from MBDocValR where NZDoc = @SrcRecID
       …
      select @RecCount=(@RecCount+count(*)) from MBDocValR7 where NZDoc = @SrcRecID
   end
   else
   begin
      if @SrcObj='А'
      begin
         select @RecCount=(@RecCount+count(*)) from MBAnalit where Analit = @SrcRecID
         select @RecCount=(@RecCount+count(*)) from MBAnValR where Analit = @SrcRecID
         …
         select @RecCount=(@RecCount+count(*)) from MBAnValR7 where Analit = @SrcRecID
      end
      else
      begin
         if @SrcObj='С'
            select @RecCount=(@RecCount+count(*)) from MBPlanAcc where XRecID = @SrcRecID
         else
         begin
             …
         end
      end
   end
   select @RecCount as 'RecCount'
Если строить запроса таким образом, что он будет содержать только то что должно выполняться, например при @SrcObj = 'Д' сразу запрос вида:
   begin
      select @RecCount=(@RecCount+count(*)) from MBDoc where NZ = @SrcRecID
      select @RecCount=(@RecCount+count(*)) from MBDocValR where NZDoc = @SrcRecID
       …
      select @RecCount=(@RecCount+count(*)) from MBDocValR7 where NZDoc = @SrcRecID
   end
То время его выполнения, использование процессора и количество логических чтений сокращается, в среднем, в два раза. Почему?

Ответ:
Вероятно много времени уходит на анализ запроса и построение плана его выполнения. Т.к. план выполнения запроса строится до начала выполнения, то SQL Server не может определить какая из частей будет выполняться и строит план на каждую часть. А т.к. они довольно сложные, то и общее время выполнения запросы существенно возрастает. Необходимо либо упрощать такие запросы   (например так, как сделано в примере), либо выносить такие запросы в ХП, план выполнения которых строится при первом использовании и далее используется уже готовый.


Вопрос:
Как удалить или обновить только конкретное кол-во записей(например 1 запись), при том что под условие попадает несколько записей ?

Ответ:
Нужно перед командой DELETE или UPDATE установить количество обрабатываемых записей используя команду SET ROWCOUNT N, где N - количество обрабатываемых записей в командах SELECT, INSERT, UPDATE и DELETE. Этим методом нужно пользоватся очень осторожно, т.к. ограничение количества обрабатываемых записей учитывается в триггерах. Т.е. если на таблице, из которой удаляются записи, есть триггер   на удаление, то все команды SELECT, INSERT, UPDATE и DELETE, используемые в триггере, будут обрабатывать только ограниченное командой SET ROWCOUNT кол-во записей.
Чтобы отключить ограничение на кол-во обрабатываемых записей нужно выполнить SET ROWCOUNT 0.
Команду SET ROWCOUNT можно использовать в MS SQL 6.5 в команде SELECT для ограничения кол-ва выводимых записей, тогда как в MS SQL 7.0 появилась возможность ограничивать прямо в команде - конструкция вида SELECT TOP N ... .
ПРИМЕЧАНИЕ. Описанное выше является особенностью MS SQL Server и на других серверах может не работать. Поэтому использование этой особенности не рекомендуется.


Вопрос:
Существовала таблица Tbl1 с полями типа Text и Image. У таблицы были индексы. Выполнили следующие действия:
• переименовыли Tbl1 в OldTbl1 с помощью хранимой процедуры sp_rename;
• создали таблицу с именем Tbl1 со всеми полями которые есть в таблице Tbl1, но у одного поля увеличили размер;
• перенесли все записи из OldTbl1 в Tbl1. Text и Image поля переносили и вместе со всеми полями с помощбю insert - select, и отдельно - через UpdateText.
В итоге получили, что внешними средствами (например, IS-Builder) из Text/Image полей можно считать только 64 КБайта. Хотя в БД содержимое полей не обрезано - это видно с помощью datalength(). Что делать? Проблема наблюдалась на MS SQL Server 6.5 и MS SQL Server 7.0

Ответ:
Для исправления необходимо либо удалить табллицу OldTbl1, либо удалить все индексы на таблице OldTbl1 и заново создать их на таблице Tbl1.


Вопрос:
Пытаюсь достать (в Query Analyzer) поле типа text из таблицы. Длина результата - 256 символов, хотя заведомо известно, что лежит там гораздо больше. Как быть?

Ответ:
В пункте меню Query/Current Connection Options... на закладке Advanced можно указать максимальное количество символов на колонку (Maximum characters per column). По умолчанию стоит 256 символов.


Вопрос:
При выполнении скриптов в Query Analyzer (например из поставки ISBuilder) выдается непонятное сообщение об отсутствии в таблице полей, причем за поля принимается содержимое символьной строки заключенной в двойные кавычки. Например на запрос select "СТРОКА" выдается сообщение   Invalid column name 'СТРОКА'. Почему?

Ответ:
Возможно в свойствах Query Analyzer установлено использование стандарта ANSI в обозначении строк, а он предполагает для обозначения строк только одинарные кавычки. Необходимо зайти в пункт меню File/Configure и на закладке "New Connections" убрать галочку против пункта "Use ANSI quoted identifers".


Вопрос:
Можно ли быстро изменить регистр (с большого на маленький) символов в Query Analyzer?

Ответ:
Воспользуйтесь комбинацией клавиш Crtl+Shift+U для перевода в заглавные буквы и Crtl+Shift+L для перевода в строчные. Есть одно замечание - работает только для символов из латинского алфавита.


Вопрос:
Пишу select, в котором использую case по нескольким полям. Например:
select case when (gpodr.Kod is null) and (gpodr1.Kod is null) then 'Прочее'
                           when (gpodr1.Kod is null) then 'АЗС'
                           else 'ТТЦ'
               end,
               sum(d.Summa2)
....
Группировку нужно делать по всем полям, используемым в case? Будет ли такая группировка корректна?

Ответ:
Да, по всем: Group By gpodr.Kod, gpodr1.Kod. Иначе будет выдано сообщение об ошибке.


Вопрос:
Нужно ли включать в секцию GROUP BY запроса SELECT константы, если они встречаются в списке полей выражения SELECT? Как строить GROUP BY, если в списке поле выражения SELECT есть сложные вычисляемые выражения, основанные на нескольких столбцах?

Ответ:
Нет, константы включать не нужно - возникнет ошибка. MS SQL сам поймет, что нужно "группировать" и по константе тоже. Если в списке полей выражения SELECT есть сложные выражения, включающие несколько столбцов, можно эти же выражения перенести и в секцию GROUP BY, но лучше будет, если каждое из встречающихся полей вынести отдельно.
Пример правильного и красивого запроса:
   select a, b, c, sum(d), '01.01.2001',
             (case
                when (e+f>g) and (e+f<=g*2) then h
                when e+f>g*2 then h-g
                else 0
               end)
      from table_abcdefgh
    where a>b
    group by a, b, c, e, f, g, h


Вопрос:
Можно ли отменить удаление таблицы (drop table)?

Ответ:
Можно, если выражение drop table находится внутри транзакции и транзакция будет отменена командой ROLLBACK TRAN.


Вопрос:
Как функциями Transact-SQL получить имя текущего пользователя БД и его login?

Ответ:
Для получения имени пользователя БД используется функция user_name(). Для получения login-а SQL-сервера - функция suser_name().
Пример:
select user_name() -- возвращает dbo
select suser_name() -- возвращает sa


Вопрос:
Как в SQL запросе сформировать текстовую строку из значения типа дата, чтобы дни и месяцы выводились по два символа (01, 02, 03 и т.д.), для корректной группировки по данной строке?

Ответ:
Используйте    select convert(varchar,getdate(),112) - для конвертации даты строку формата ГГГГММДД и функцию substring() - для выделения дня, месяца и года из созданной строки. Пример для получения номера дня - substring(convert(varchar,getdate(),112),7,2)
Другой вариант   - для сортировки использовать функцию datepart(), которая возвращает целое значение.


Вопрос:
В каких случаях ROLLBACK TRANSACTION прерывает выполнение пакетного запроса к SQL-серверу и когда происходит выполнение последующих команд?

Ответ:
Если произошла ошибка и была вызвана команда ROLLBACK TRANSACTION в триггере, то последующие команды не выполнятся.
   Если ошибка была в хранимой процедуре или в самом пакетном запросе, то в переменной   @@ERROR будет возвращен код ошибки и продолжится выполнение последующих команд уже вне транзакции. Все изменения, которые были после отката транзакции будут сохранены на сервере, даже в том случае если после клиент пошлет ROLLBACK TRANSACTION.


Вопрос:
Выполняется такой запрос:
   if exists (select * from sysobjects where id = object_id('MBAnAccRptODR') and sysstat & 0xf = 3)
      select convert(datetime,isnull(max(DateLastOper),'01.01.1900'),4)
         from MBAnAccRptODR
   else
      select '01.01.1900'
И, хотя таблицы MBAnAccRptODR в БД нет, возникает ошибка "Invalid object name 'MBAnAccRptODR'". Т.е. как бы выполняется команда "select … from MBAnAccRptODR"
Если же выполнить такой запрос:
   if exists (select * from sysobjects where id = object_id('MBAnAccRptODR') and sysstat & 0xf = 3)
      select '02.02.2000'
   else
      select '01.01.1900'
то, если нет таблицы MBAnAccRptODR, возвращается значение '01.01.1900', т.е. команду select '02.02.2000' не выполняет. Если же таблица есть, то возвращается значение '02.02.2000'.
В чем тут дело и как быть?

Ответ:
Дело в том, что SQL перед выполнением анализирует весь пакета команд не обращая внимание на условия. А т.к. таблицы MBAnAccRptODR нет в БД, то и возникает ошибка. В этом случае необходимо воспользоваться командой EXEC:
   if exists (select * from sysobjects where id = object_id('MBAnAccRptODR') and sysstat & 0xf = 3)
      exec("select convert(datetime,isnull(max(DateLastOper),'01.01.1900'),4)
                  from MBAnAccRptODR")
   else
      select '01.01.1900'
Кстати, по этой же причине не пройдет вот такая комбинация:
   create table T(F1 int)
   insert into T(F1) values(1)
Необходимо либо разделить их командой go (тогда это будут разные пакеты команд):
   create table T(F1 int)
   go
   insert into T(F1) values(1)
Либо использовать exec():
   exec("create table T(F1 int)")
   exec("insert into T(F1) values(1)")


Вопрос:
На MS SQL 6.5 выполняется truncate таблицы, после этого таблица заполняется новыми данными (несколько десятков тысяч записей). После этого скорость выполнение запросов, в которых участвует эта таблица, резко падает. Хотя до truncate количество записей в таблице было примерно таким же и все необходимые индексы установлены. В чем дело и как исправить?

Ответ:
Было замечено, что после truncate и заполнения таблицы SQL Server перестает использовать индексы, наложенные на эту таблицу. Причем обычно после закрытия текущего соединения с сервером и установки нового все приходит в норму.


Вопрос:
В T-SQL есть оператор LIKE, который использует спец. символы:
• '%' - любые один или несколько символов;
• '_' - один любой символ.
А как искать строки, в которых присутствуют эти спецсимволы?

Ответ:
Такие символы нужно заключать в квадратные скобки:
Такие символы нужно заключать в квадратные скобки:
• like '5[_]' - будут выбираться строки, содержащие '5_', а не '51', '5a' и т.д.;
• like'ffff[%]' - будут выбираться строки, содержащие 'ffff%', а не 'ffffaaaa', 'ffff1' и т.д.;
• like 'MB_an[_]' - будут выбираться строки, содержащие 'MB'+ любой символ+'an_'.
• like '%[[]%' - будут выбираться строки, содержащие '['
• like '%]%' - будут выбираться строки, содержащие ']'
• like '%[[]]%' - будут выбираться строки, содержащие '[]'


Вопрос:
Есть такие данные (таблица tmpSample):
Column1 Column2 Column3
-------- -------- --------
10 А А
20 Б А
-5 А А
-15 В Б
25 В Б
Нужно выдать: комбинацию полей Column2 и Column3, сумму Column1. При этом нужно выдать только положительные суммы. И самое главное: данные надо отсортировать по столбцу Column3. Менять выдаваемые данные и добавлять новые столбцы нельзя.
Т.е. должны получить на выходе:
Column2+Column3 Sum(Column4)
---------------- -------------
АА 5
БА 20
ВБ 10
Запрос получается таким:
select Column2+Column3, sum(Column1)
   from tmpSample
group by Column2+Column3
having sum(Column1)>0
order by Column3
Проблема в том, что сортировка по столбцу Column3 запрещена - выдает ошибку SQL Server. Что делать?

Ответ:
Нужно добавить группировку по колонке Column3:
...
group by Column2+Column3, Column3
...


Вопрос:
Выполняю вот такой запрос:
select round(sum(isnull(vr.Summa3T,0)),2),
          round(sum(isnull(vr.Summa5T,0)),2)
   from MBAnValR vr , MBAnalit mon
   where vr.Analit=1074303
      and mon.Analit=vr.MonthT
      and convert(int,mon.Kod)<8
Выдает сообщение, что не может конвертировать 'Г3' в INT4. Единственное поле типа varchar - mon.Kod. Хотя точно известно, что в тех записях, которые попадают под запрос (условие на vr.Analit и связь таблиц vr и mon) гарантированно имеют от '01' до '12' - т.е. должен нормально конвертироваться в int. А значение 'Г3' действительно присутствует в этой таблице в поле Kod, но в записях, которые не должны трогаться в этом запросе. А раньше этот запрос работал. Как оказалось, был удален первичный ключ на таблицах MBAnalit (поле Analit) и таблице MBAnValR (поля MBAnalit и NumStr). В чем же было дело?

Ответ:
Видимо дело было в том, что когда были удалены индексы, процессор запросов SQL Server-а пришел к выводу, что ему необходимо сканировать ВСЮ таблицу MBAnalit, проверяя условие convert(int,mon.Kod)<8 для КАЖДОЙ записи в MBAnalit. Мораль такова - надо воздерживаться от написания условий, корректность которых зависит от порядка выполнения.


Вопрос:
Сколько столбцов может быть в таблице?

Ответ:
В MS SQL Server - 6.5 -   250
В MS SQL Server - 7.0 - 1024


Вопрос:
В чем отличие полей char и varchar?

Ответ:
В   результате экспериментов было   выяснено, что если   поле имеет признак NOT NULL, то тип VARCHAR занимает в таблице места столько,   сколько значащих байт   в строке (последние пробелы   отрезаются), а   CHAR занимает   столько -   сколько задано и добивает при необходимости пробелами. Если поле имеет   признак   NULL,   то   тип   CHAR   и VARCHAR ведут себя одинаково. Microsoft также утверждает, что   доступ к полю CHAR идет быстрее, но на сколько (или во сколько) неизвестно.


Вопрос:
Имеется ХП:
create procedure Proc1 @NumInvc varchar(20) as
begin
if @NumInvc='AAAAA'
   select * from Tbl1 where Name=@NumInvc
else
   select * from Tbl1 where Kod=char(int,@NumInvc)
end
При таком вызове ХП   exec Proc1 @NumInvc='AAAAA' выдается сообщение   о том, что   значение 'AAAAAA' не   может быть   конвертировано в   INT4. Установлено,   что ругается на строку "where Kod=char(int,@NumInvc)". Что делать?

Ответ:
Необходимо в ХП определить переменную varchar(20) и параметр @NumInvc переслать в эту переменную. В дальнейшем использовать только эту переменную. О причинах могу предположить следующее. Convert() и некоторые другие являются встроенными функциями SQL, отличительным признаком является возможность использовать в запросах. Так вот, похоже, для этих функций и для параметров ХП, перед выполнением ХП происходит прекомпиляция и начальные проверки. Получается, что вместо параметра SQL подставляет его значение и сразу пытается выполнить функции. И все это по всей ХП сразу, не обращая внимания на условия и прочее.


Вопрос:
SQL-сервер не принимает дату в таком виде - '13.12.97'. Что делать?

Ответ:
По умолчанию   дата в SQL-запросе   принимается в следующем   формате - mdy. Изменить это можно с помощью команд SET DATEFORMAT. Синтаксис: set dateformat mdy|dmy|ymd. Действует на текущий коннект.


Вопрос:
Имеется вот такой запрос:
select d.Kod, d.NameAn, dd.Kod, dd.NameAn,
                      charindex(substring(d.NameAn,1,patindex('%(И)%',d.NameAn)-1),dd.NameAn)
from MBAnalit d, MBVidAn v, MBAnalit dd
where v.Kod='ДОГ'
   and v.Vid=d.Vid
   and dd.Vid=v.Vid
   and patindex('%12%',d.NameAn)<>0
   and charindex(substring(d.NameAn,1,patindex('%12%',d.NameAn)-1),dd.NameAn)>0
   and dd.HighLvl=d.HighLvl
   and dd.Analit<>d.Analit
   and patindex('%12%',dd.NameAn)=0
При выполнении этого запроса выдается сообщение об ошибке "Invalid length parameter passed to the substring function". Если же в where убрать условие "and charindex(substring(d.NameAn,1,patindex('%12%',d.NameAn)-1),dd.NameAn)>0", то все работает. Но ведь то же самое выражение остается в select и все работает. Почему?

Ответ:
Во-первых, следует иметь в виду, что SQL Server будет проверять все условия в where совсем не в том порядке, в котором они написаны. Для корректного выполнения условия "charindex(…" необходимо, чтобы сработало условие "and patindex('%12%',d.NameAn)<>0". В противном случае возможны ситуации, когда выражение "patindex('%12%',d.NameAn)" будет иметь значение 0 и, таким образов в substring() будет передано отрицательное значение, а это не допустимо.
В то же время выражения в select будут выполняться уже после того, как выполнятся ВСЕ условия в where - т.е. выражение "charindex(…" в select работает тогда, когда "patindex('%12%',d.NameAn)" гарантированно не имеет значения 0.
Следует также отметить, что при малейшем изменении запроса (например, добавить или убрать таблицы в связях) или даже при изменении состояния индексов (это может привести к изменению плана выполнения запроса) выполнение запроса может измениться, и он будет работать нормально.
Отсюда мораль - не надо в where писать связки условий так, что результат зависит от порядка выполнения запросов.


Вопрос:
Написал команду типа "delete … from … where …", но удалил не те данные, которые хотелось бы. Можно ли вернуть?

Ответ:
К сожалению, вернуть эти данные уже не удастся. Если только восстановить базу данных из резервной копии. На будущее можно порекомендовать следующие способы предохранения от такой случайности.
Способ 1. Самый лучший. Внимательно проверять запрос, перед тем как его выполнить.
Способ 2. Преобразуйте delete в select с теми же from и where и проверьте, что он возвращает. Например, требуется выполнить такую команду:
   delete from Table1
      from Table2 t2
      where t2.Fld1=Table1.Fld2
Проверим, что будет удалено таким запросом:
   select Table1.*
      from Table1, Table2 t2
      where t2.Fld1=Table1.Fld2
Способ 3. Это способ требует большой внимательности. Суть способа - использование механизма транзакций для отката возможных некорректных действий. Для этого:
• перед удалением начинать явно транзакцию командой "begin transation";
• после удаления в этом же коннекте посмотреть, что реально удалилось и, если все сработало правильно, завершить транзакцию командой "commit transation";
• если же что-то пошло не так, то можно откатить транзакцию командой "rollback transaction".


Вопрос:
Есть ли ограничения на количество таблиц в запросе?

Ответ:
Есть. В MS SQL 6.5   - 16 таблиц. Причем в это количество входят таблицы в подзапросах и во VIEW. Пока известен только   один способ борьбы с ограничением - создавать рабочие таблицы и выносить часть запроса в них. Причем при использовании большого количества (6 и более) таблиц в MS SQL 6.5 резко замедляется выполнение запроса и резко увеличивается загрузка процессора. Иногда может помочь, если перед выполнением запроса послать команду "set forceplan off". Эта команда заставляет сервер не умничать, а выполнять запрос так как ему сказали, не оптимизируя его.   После выполнения запроса необходимо послать команду "set forceplan on".
В MS SQL 7.0 ограничение на количество таблиц значительно слабее (кажется, там можно использовать 256 таблиц). Причем не наблюдается замедления при увеличении количества таблиц.


Вопрос:
Что будет раньше - ошибка на неуникальность первичного ключа или сработает триггер ?

Ответ:
Ошибка возникнет раньше, также   как и ошибки foreign key, unique constraint и check constraint. Триггер   при этих ошибках даже не вызывается.


Вопрос:
Выделили переменную размером 255   символов, присвоили ей строку из   4 символов, а затем    пытаемся дописать к этой строке какую-нибудь переменную. Результат никакой.

Ответ:
MS SQL Server (по крайней мере 6.5) умничает по поводу   выделения памяти. Если строке присвоено 4 символа, то он и выделит 4, а не 255 как просили. Решением может служить   первоначальное   присвоение   не   константы,   а переменной, чтобы он не смог догадаться о ее длине.


Вопрос:
Была записана такая команда:
select @FF=FF from Tbl where FF=10
В результате этой команды ни одна строка не была найдена, но @FF не равна null. Почему?

Ответ:
SQL при неудачном поиске не присваивает значение NULL переменной. В ней остается то значение, которое было до вызова команды (это может быть и NULL). Лучше всего перед указанным селектом затолкать в переменную какое-нибудь значение. Например, NULL.


Вопрос:
Возможен ли рекурсивный вызов триггеров?

Ответ:
Прямой рекурсии триггера на одно и то же событие не происходит. Косвенная рекурсия   возможна. Т.е. -   если в триггере   на update сделать   update   этой   же   таблицы,   то   триггер   второй раз не вызовется, но если   update будет сделан в ХП,   которая вызвана в триггере, то вызовется   уже другой экземпляр   триггера на update. Также триггеры на разные события вызываются друг из друга. Только для всего этого необходимо, чтобы параметр сервера 'nested triggers' имел значение 1. Проверить это можно, вызвав команду "sp_configure 'nested triggers'" и проверив колонку "run_value".


Вопрос:
После смены имен полей в таблице обращение к ней через view ведется со старыми полями. Что делать?

Ответ:
MS SQL Server при создании view запоминает названия полей. Чтобы это дело обновить, необходимо повторно создать view.


Вопрос:
Если в where написано t.LAcc=s.CHET, и оба эти поля равны null, то условие ложно. Почему?

Ответ:
Дело в том, что SQL Server очень трогательно относится к значениям null. Если поле может принимать значение null, то лучше всего в условия использовать функцию isnull(). Например, так - isnull(t.LAcc,0)=isnull(s.CHET,0).


Вопрос:
После генерации при первом выполнении триггер работает с ошибкой. В дальнейшем работа происходит без ошибок. Почему?

Ответ:
Такая ситуация у меня была когда создавал курсор на 5 полей, а в fetch использовал 4 переменных. Такая ошибка может привести к серьезным проблемам - вплоть до зависания сервера и разрушения БД.


Вопрос:
Заношу в строковое   поле значение   "" (пустые кавычки). При последующем селекте вижу в поле один пробел.

Ответ:
Microsoft   говорит, что при   попытке послать в   строковое поле типа varchar() значение   "", туда пишется один пробел (single space). А тип char() заполнится пробелами.


Вопрос:
Не работает вот такой update
   update Tbl
      set Tbl.Fld1=t2.Fld1
      from Tbl t2
      where Tbl.Fld2=t2.Fld2
Говорит 'ambigous column name ...'. Что делать?

Ответ:
Надо делать так:
   update t1
      set t1.Fld1=t2.Fld1
      from Tbl t1, Tbl t2
      where t1.Fld2=t2.Fld2


Вопрос:
Есть примерно такой запрос:
   select *
      from Tbl1 t1
      where isnull(t1.Fld1, 123)=123
При небольшом количестве записей работает прекрасно, но с увеличением количества записей скорость выполнение резко падает, хотя индекс на поле Tbl1.Fld1 установлен. В чем дело?

Ответ:
Дело в том, что связывание таблиц с использованием встроенных функций T-SQL (isnull, convert, substring и т.д.) отменяет использование индексов. Соответственно скорость выполнения резко падает. Можно предожить записать запрос таким образом:
   select *
      from Tbl1 t1
      where t1.Fld1=123
          or t1.Fld1 is null

Вверх

<<Назад

Главная| ИС.. | Моделирование | Проектирование |ТД | Разработка | Интерфейс | Статьи | Ссылки | Автор
DimDim SoftWare Мастерская Dr. dimdim Copyright 2003-2004
Администратор info-system@mail.ru
Последнее обновление 26-Дек-2003