Разделы
Публикации
Популярные
Новые
|
Главная » Оптимизация производительности transact 1 ... 4 5 6 7 8 9 10 ... 55 с плавающей запятой в приложениях SQL Server, в ироиедурах, реализованных на обычных языках программирования. Единственное рещение, устойчивое к ошибкам, заключается в использовании значений с фиксированной запятой вместо типов с плавающей запятой. Типы данных decimal и numeric не зависят от ошибок округления, потому что не являются тина.ми с плавающей запятой. Таки.м образом, они также ие могут использовать математический сопроцессор, так что вычисления будут, вероятно, более медленными, по сравнению с тина.ми с плавающей запятой. Эту медлительность .\южно компенсировать в других областях. Вывод следующий: SQL Server не может корректно обрабатывать ошибки округления при работе со зиачения.ми с плавающей запятой, так что будьте осторожны, если решите использовать типы данных float или real. Вот переписанный запрос, использующий тип данных с фиксированной запятой с точностью, равной 10, и масштабом, равиы.м 4: SET NOCOUNT ON CREATE TABLE #rand * (kl int identity. cl decimal(10.4) DEFAULT ( (CASE (CAST(RAND()+.5 AS int)*-l) WHEN 0 THEN 1 ELSE -1 END)*(CONVERT(int. RANDO * 100000) X 10000)*RAND() INSERT #rand DEFAULT VALUES INSERT #rand DEFAULT VALUES INSERT #rand DEFAULT VALUES INSERT #rand DEFAULT VALUES INSERT #rand DEFAULT VALUES INSERT #rand DEFAULT VALUES INSERT #rand DEFAULT VALUES INSERT #rand DEFAULT VALUES INSERT #rand DEFAULT VALUES INSERT #rand DEFAULT VALUES SELECT * FROM #rand SELECT SUM(cl) FROM #rand SELECT * INTO #rand2 FROM #rand ORDER BY cl SELECT SUM(cl) FROM #rand2 SELECT * INTO #rand3 FROM #rand2 ORDER BY ABS(cl) SELECT SUM(cl) FROM #rand3 DROP TABLE #rand. #rand2. #rand3 kl cl 1 2450.3156 2 2248.7416 3 2014.1533 4 823.7021 5 -501.3661 6 -261.9785 7 1389,4180 8 -1608.7563 9 -850.2965 10 -3709.9473 1993.9859 1993.9859 1993,9859 Деление на нуль До выхода SQL Server версии 7.0 при делении числового значения на нуль результат получался равны-м NULL Теперь но умолчанию это не так. При делении числа на нуль вы получите ошибку: SELECT 1/0 Server: Msg 8134. Level 16. State 1, line I Divide by zero error encountered. Вы можете из.менить поведение ирогра.\ьмы с помощью установок сессии ANSI WARNINGS и ARITHIGNORE. По умолчанию предупреждения ANSI включены (ANSI WARNINGS) при соедпиенип с сервером с использованием ODBC или OLEDB, а ARITHIGNORE - отключена. Вот запрос, возвращающий NULL при делении на нуль: SET ANSI WARNIi\GS OFF SET ARITHIGNORE ON SELECT 1/0 NULL (Если вы вьиюлняете этот запрос из Query Analyzer, ва.м необходн.мо отключить предупреждения ANSI в диалоге Current Connection Options, чтобы этот запрос заработал.) Веселые деньги Между денежнылн! типа.ми - money и smalimoney - и л]5угими числовы.\Н! типами данных паб.подается песоответс:гвпе. Все числовые данные, кроме money и smalimoney, неявно преобразуются к симьо.и>ным строкам во время операций INSERT и UPDATE. У money н smalimoney, но некоторым нричина.м, возникают с этим проблемы. Например, следующпГ! ;ипрос сгенерирует сообщение об ошибке: CREATE TABLE r.est (cl money) -- He делайте так -- плохой SOL INSERT #te5t VALUESC1232; SELECT * FROM #Lest GO DROP TABLE #test Вы можете изменить тип данны.х столбца с1 на любой числовой - от tinyint до float, ~ и запрос выполнится, как вы и ожидали. Денежные типы, по некоторым прнчина.\, более привередливы. Для них требуется явное преобразование, как здесь: CteAfL TASLL fftesi (cl яог.ьу] INSERT #tesi SELECI CASTC1232 AS money) SELECT * FROM #test DROP IABlE #tesi cl 1232.COOC Форматирование числовых данных в дополнение к использованию CAST() и CONVERT() для преобразования числовых типов данных к строкам в соответствии с форматом, вы можете применить функцию STR(). STR() лучше, чем универсальные CAST() и CONVERT(), потому что с помощью нее можно выравнивать зиачеиия по правому краю и указывать количество десятичных разрядов. Вот несколько примеров: SELECT STR(123.10) AS Str, CAST(123 as char(lO)) AS Cast Str Cast 123 123 SELECI STR(PI().7,4) AS Sir, CAST(PI() AS char(7)) AS Cast Str Cast 3,1416 3,14159 BLOB SQL Server предоставляет поддержку полей тина BLOB (binary large object -больших двоичных объектов), с использованием типов image и text (а таюке ntext), С помощью этих типов данных можно хранить и получать поля размером до 2 Гбайт. С появлением строк длиной 8000 байт необходи.мость в них уменьшилась, но, так как в базах данных SQL Server все чаще начинают хранить различные иетрадициоипые типы данных, BLOB-поля однозначно должны остаться. Проблемы Реализация BLOB-полей в SQL Server несколько неповоротлива, и вы должны дважды подумать, прежде чем включать их в свои таблицы. BLOB-поля хранятся в цепочке страниц, отдельной от записи, к которой они принадлежат. На самом деле в самом столоне типа BLOB хранится указатель длиной шестнадцать байтов на первую страницу в цепочке страниц столбца. BLOB хранятся не как остальные типы данных, и вы пе можете обращаться с ними так же, как с другими типа.ми данных. Например, вы не можете объявлять локальные переменные типа text или image. Если вы попытаетесь это сделать, то получите сообщение о синтаксической ошибке. Вы можете передавать значения text или image в ка- честве параметров хранимых процедур, которые вы затем можете нсполыювать в DML-операторах, но не сможете присвоить другое значение переменной или сделать с ней что-то еще. Вот хранимая процедура, которая это иллюстрирует: CREATE PROCEDURE inserttext (p-instext text AS SET KOCOU\T ON SELECT (oinstext AS Inserting CREATE TABLE #testnotes (kl mt icentity. notes text; INSERT ftestnotes (notes) i/ALUES ((amstext) SELECT DATALENGK(notes). * FROM ftestnotes DROP TABLE #testnotes EXEC inserttext TEST Inserting TEST Kl notes 4 1 TEST Здесь (giinstext - параметр типа text, который хранимая процедура вставляет в столбец notes типа text. Так как вы не можете объявлять локальные переменные типа text, (giinstext нельзя присвоить другой текстовой пере.мепной (хотя можно присвоить обычной переменной типа char или varchar) и также этой переменной нельзя присвоить другое значение. По большому счету, ее можно применять только вместо текстовых значений в DML-командах (Data Management Language - язык управления данными). Вы также не можете обращаться к BLOB-столбцам в предложении WHERE с исггользованием знака равенства - вместо этого вы должны применять предикат LIKE, PATINDEXO или DATALENGTH(). Вот пример: CREATE TABLE ftestnotes (kl int identity, notes text) INSERT ftestnotes (notes) VALUES (test) -- He запускайте это -- Этот пример не работает SELECT * EROM #testnotes WHERE notes=test DROP TABLE ftestnotes GO Хотя мы только что вставили значение <jtest с помощью оператора INSERT, SELECT не может получить его, используя традиционный подход. Вместо :-)того вы должны сделать нечто, подобное следующе.му: SELECT * FROM ftestnotes WHERE notes LIKE test Традиционные правила, регулирующие доступ к типам данных и столбцам, не применяются к ВЕОВ-столбца.м, и вы должны помнить об этом, если решите их использовать. Получение данных типа BLOB BLOB расшифровывается как большое! двоичный объею (Binary Large OBject). В отличие от небольших BLOB, большие поля BLOB обычно не возвраишют с помощью простого оператора SELECT. Хотя вы можете контролировать количество данных, возвращаемых операторо.м SELECT, с по.мощью SET TEXTSIZE, ваше клиентское приложение, возможно, не cюжeт правильно работать с больши\н1 объе.ма.ми BLOB-данных. Более того, так как вы не .можете объявлять локатьныс переменные типа text или image, вы не можете использовать SELECT для присваивания больших BLOB-данных нере.менной для дальнейшей обработки. В.место этого вы должны использовать ко.\инду READTEXT для доступа к столбцу но частям. READTEXT .может работать как со столбца.\н1 типа text, так и со столбцами типа image. Она иринн.мает четыре параметра: и.мя столбца для чтения, указатель на содержащийся в нем текст, смещение, с которого необходимо начинать чтение, и раз.мер блоков для чтения. Для получения указателя на данные BLOB-столбца применяется функция TEXTPTR(). Этот ука;5атель представляет собой значение типа binary(16), которое указывает на первую страницу BLOB-данных. Вы .можете проверить правильность указателя с помощью с})ункции TEXTVALID(). Вот пример, иллюстрирующий использование TEXTPTR() и READTEXT: DECLARE gtextptr Ыпагу{1б) BEGIN TRAN SELECT (atextptr=TEXTPTR(prjr,fo) FROM pub info (HOLDLOCK) WHERE pub id=1389 READTEXT pub 1nfo.pr info ?textptr 29 20 COMMIT TRAN Algodata Infosystems Обратите вни.маиие на ири.менение транзакции и ключевого слова HOLDLOCK, чтобы гарантировать правильность указателя с мо.мента его получения с по.чющью READTEXT. Так как другие пользователи .могут изменить BLOB-столбец, пока мы с ним работаем, указатель, полученный с помощью TEXTPTR(), может стать нспра-внльны.м между его первоначальны.м получением и вызовом READTEXT. Чтобы этого ие произошло, мы задействуем транзакцию. Обычно думают, что примене-iHie транзакций ограничивается управлением модификацией данных, но, как вы только что убедились, их также можно использовать, чтобы гарантировать вос-производп.мость чтения. Вместо того чтобы указывать фиксированное с\ющение и длину блока для чтения, чаще всего применяют функцию PATINDEXO, чтобы найти подстроку в BLOB-поле и извлечь ее, как показано далее: DECLARE (atextptr binary(16). @patindex int. (apatlength int BEGIN TRAN SELECT (atextptr=TEXTPTR(pr info). (apatindex=PATINDEX( lAlgodata InfosystemsV.pr info)-l. iapatlength=DATALENGTH( Algodeta Infosystems) FROM pub info (HOLDLOCK) WHERE PATINDEX(Wlgodata Infosystems.pr info)<>0 READTEXT pub info.pr info @textptr (apatindex gpatlength COMMIT TRAN pr info Algodata Infosystems Обратите внимание на использование PATINDEX() и для фильтрации запроса, и для присваивания значения перемеиио!! @patindex. Запрос должен вычесть единицу из результата PATINDEX(), ното.му что значения PATINDEX() начинаются с единицы, тогда как READTEXT - с ну;[я, Как я уже упоминал ранее, PATINDEX() работает подобно LIKE, за исключением того, что .может также вернуть смептение найденного образца или строки. Для обработки больпшх сег.ментов необходн.мо в цикле пройти BLOB с помощью READTEXT, читая по одно.му блоку за раз. Вот при.мер: DECLARE (atextptr binary(16). (Pblobsize int, @chunkindex int, Ochunksize int SET TEXTSIZE 64 -- Очень маленькое значение установлено только для иллвстрауи/ BEGIN TRAN SELECT (atextptr=TEXTPTR(prjnfo), (ablGDsize=OATALENGTH(pr info), l?chunkindex-0, (achunksi2e=CASE WHEN gOTEXTSIZE < (abiobsize THEN KaTEXTSIZE ELSE (abiobsize END FROM pubjnfo (HOLDLOCK) WHERE PATlNDEXCIAlgodata Infosyste.msr ,рг 1пГо)<>0 IF ((atextptr IS NOT NULL) AND ((achunksize > 0) WHILE (gchunkindex < (abiobsize) AND ((a(aERROR=0) BEGIN READTEXT pub info.pr info @textptr ?chunkindex lachunksize SELECT (achunk 1 ndex=(achunk 1 ndex+(achunksi ze. iachunksize=CASE WHEN ((achunkmdex+Ochunksize) > @blobsi2e THEN (ablobsize-iachunkindex ELSE Achunksize END COMMIT TRAN SET TEXTSIZE 0 -- Устанавливаем значен/.е по умолчани.ю (40%) (результаты сокращены) pr 1nfo This is sample text data for Algodata infosystems. publisher 133 pr info 9 in the pubs database. Algodata Infosystems is iocatea in Berke pr info ley. California. Самая большая хитрость в этом запросе - тот факт, что READTEXT не позволяет читать данные после Koinja BLOB. То есть, если BLOB состоит из 100 стьм-волов, вы не можете указать стартовую точку 90 и блок размером 30 и ожидать, что получите последтше 10 сиашолов - вместо этого READTEXT вернет ошибку. Так что запросу приходится делать работу READTEXT за нее - он вычисляет точный размер оставшихся данных и заботится о то.м, чтобы его не превысить. Чтобы код был как можно более колнгактным, этот запрос использует тот факт, что SQL Server вычисляет выражения слева направо. В начальном операторе SELECTT переменная (abiobsize используется позже в списке SELECTT, сразу после того как ей присвоено значение этим же самым оператором. Это работает, пото- му что SQL Server вычисляет список слева направо. Оператор SELECT в иикле исполь,зует ту же са.мую технику. Переменная @chunkindex при.меняется в других местах оператора SELECT, который также прпсванвает ей значение. Не гарантируется, что .это поведенне останется таким же в будущих версиях продукта, и его следует ири.менять осторожно. В недавних нрп.мерах ,мы задействовавши! HOLDLOCK, чтобы гарантировать, что указатель, полученный ранее в запросе, останется правпльпы.м позже, - для гарантии воспроизводимости чтения. В результате применения HOLDLOCK операторо.м SELECT накладывается блокировка чтения, которая действует до конца транзакции. В зависи.мости от текущего уровня изоляции транзакции HOLDLOCK может быть даже и не нужен, пото.му что .мы полностью считываем сегмент, который йотом не собираемся читать заново (см. главу 14). В качестве альтернативы можно использовать SET TRANSACTION ISOLATION LEVEL, чтобы заставить сервер гарантировать повторяемость чтения, как показано здесь: DECLARE (atextptr binary(16). (ablobsize mt. (achunkindex int. (achunksize int SET TEXTSIZE 64 -- Устанавливаем очень маленькое значение только в целях иллюстрации SET TRANSACTION ISOLATION LEVEL REPEATABLE READ BEGIN TRAN SELECT (atextptr=TEXTPTR(pr info). (aDlobsize=DATALENGTH{pr info), (achunkindex=0, (achi;nksize<ASE WHEN (agTEXTSIZE < golobsize THEN (agTEXTSIZE ELSE Sblobsize END FROM pub info WHERE PATINDEXCUlgodata Infosystems.pr info)<>0 IF ((atextptr IS NOT NULL) AND ((Bchunksize > 0) WHILE ((achunkindex < (ablobsize) AND ((a(aERROR=C) BEGIN READTEXT pub info.pr info (atextptr (achunkindex (Bchunksize SELECT (achunkindex=(achunkindex+(achunksize. Ochunks-ze-CASE WHEN ((achunkindex+gchunksize) > (ablobsize THEN @blob5ize-(achunkindex ELSE (Bchunksize END END COMMIT TRAN SET TEXTSIZE 0 - Возвращаем значение по умолчанию (4096) GO SET TRANSACTION ISOLATION LEVEL READ COMMIHED -- Возвращаем уровень изоляции по умолчанию (в отдельном пакете) Когда мь[ сообщаем серверу, чтобы он гарантировал повторяемость чтения в транзакции, мы блокируем остальных пользователей, так что они не могут вносить изменения в prjnfo, пока мы работаем с ним; то же самое выполняет HOLDLOCK. Модификация данных типа BLOB Модификация BLOB-столбцов с данными типа text или image, размер которых .меньше или равен 8000, происходит так же, как и .модификация столбцов любых других типов данных. Вы можете использовать INSERT, UPDATE и ограничения DEFAULT для работы с этими значениями, как и в случае других типов данных. Вот при.мер: CREATE TABLE #testnotes (kl int identity, notes text DEFAULT SPACE(IO)) INSERT #testnotes DEFAULT VALUES INSERT #testnotes (notes) VALUES (REPLICATE(X.20)) UPDATE #testnotes SET notes=REPLICATE(V.10) WHERE kl=l SELECT * FROM #testnotes 1 YYYYYYYYYY 2 XXXXXXXXXXXXXXXXXXXX Чтобы записывать значения больше 8000 байт с помощью Transact-SQL, не-обходи\ю применить команду UPDATETEXT или WRITETEXT. С помощью UPDATETEXT можно модифицировать часть BLOB-поля, тогда как WRITETEXT полностью переписывает все содержимое. Вообще говоря, ко.манда UPDATETEXT более гибкая по сравнению с WRITETEXT, так остановите же свой выбор на ней, если вам необходимо записывать большие объемы данных типа text или image в BLOB-поля. Вот при.мер: CREATE TABLE ftestnotes (kl int identity, notes text DEFAULT REPLICATE(X.20)) BEGIN TRAN INSERT ftestnotes DEFAULT VALUES DECLARE etextDtr binary{16) SELECT (atextptr=TEXTPTR{notes) FROM ftestnotes (UPDLOCK) UPDATETEXT ftestnotes.notes etextptr 0 0 III SELECT * FROM ftestnotes COMMIT TRAN DROP TABLE ftestnotes к I notes I III mmnmmmm Команда UPDATETEXT принимает пять пара.метров: модифицируемый столбец, корректный указатель на него, смещение, начиная с которого будет производиться модификация, количество удаляемь[Х символов и текст для замены. Несмотря на свое название, UPDATETEXT сначала удаляет, а затем вставляет новый текст. Эта команда работает подобно функции STUFF() Transact-SQL, предназначенной для удаления части строки и замещения ее другой. Если мы укажем смещение и удаляемую длину, равные нулю, указанная на.ми строка будет просто вставлена в начало текстового поля. Как и в случае функции READTEXT, корректный текстовый указатель может быть получен с помощью функции TEXTPTRQ. Транзакции позволяют гарантировать, что указатель, полученный с помощью SELECT, является корректным, когда вызывается UPDATETEXT. Мь[ применяем UPDLOCK вместо HOLDLOCK, потому что модифицируем данные, а не просто читаем их. Вы почувствуете всю мощь UPDATETEXT, когда вам потребуется модифицировать часть BLOB, а не просто добавить в его начало новую строку или вообще заменить его новой строкой. Вот при.мер: CREATE TABLE ftestnotes (kl int identity, notes text DEFAULT ) BEGIN TRAN INSERT ftestnotes DEFAULT VALUES UPDATE ftestnotes SET notes=Women and Babies First DECLARE (atextptr binary(16). (Jpatindex int. (Ppatlength int SELECT (atextptr=TEXTPTR(notes). (apatindex=PATINDEX(IBabiesI.notes)-1. @patlength=DATALENGTH(Babies) DROP TABLE ftestnotes .< I notes FRCM Lestnoies (UFDLOCK) WHERE PATiNDEX! iJBdb.esr .nc.es)<>u UPDATETEXT #te5tnotes.notes (atextptr capalindex (apatlength Children SELEC* * FROM #testnotes COMMIT TRAN GO DROP TABLE #te5tnotes Kl notes 1 Women and Childnen Finst Здесь мы кспользовачи PATINDEX(), чтобы найти смещение в текстовом ноле, а затем ирименили UPDATETEXT для изменения строки в этом месте. Ко.манда WRITETEXT работает подобно UPDATETEXT. Так как WRITETEXT записывает поле целико.м, пара.метры смещение и длина этой ко.манде не нужны. Вот пример: CREATE TABLE #testnotes (kl mt identity, notes text DEFAULT ) BEGIN TRAN INSERT #testnotes DEFAULT VALUES DECLARE (atextptr binany(16) SELECT (atextptn=TEXTPTR(notes) FROM #testnotes (UPDLOCK) WRITETEXT #testnotes.notes (atextptr III SELECT * FROM #testnotes COMMIT TRAN DROP TABLE #testnotes kl notes 1 III Обратите внимание на использование ограничения для присваивания значения по у.молчаиию BLOB-столбцу. Так как для работь[ и UPDATETEXT и WRITETEXT требуется корректный указатель на текст, вы ие можете применить их для записи данных в BLOB-поля, содержащие NULL. Из-за этого добавление текста в новую вставленную запись становится сложнее, че.м могло бы быть. Лучший способ обойти это ограничение - установить DEFAULT-ограиичеиие на BLOB-столбец; затем, когда запись будет добавлена в таблицу, в столбце будет корректное значение, которое можно использовать для доступа с помощью отдельного запроса с TEXTPTR(). После того как вы получили корректный указатель на текст, вы .можете вызывать UPDATETEXT или WRITETEXT, чтобы поместить реа^тьные данные в BLOB-столбец. Модификация BLOB и журнал транзакций и UPDATETEXT, и WRITETEXT поддерживают опцию WITH LOG, которая определяет, будут ли вносимые и.ми из.менения записаны в журнал транзакций. По у.молчаиию модификация BLOB не вносится в журнал. К несчастью, в результате этого журнал транзакций становится неактуальным (приходится делать полные резервные копии), и необходимо, чтобы опция базь[ данных select into/bulk copy была разрешена (с по.мощью sp dboption). Всегда лучше вносить в журнал опера- ции, К01да это возможно. Это позволяет при.меиягь журши: траизактпг и со-.хранять целостность ваин[х баз данных. Конечно, cyuiecTByioT нсчстючення из этого правила - возможно, вы будете добавлят!) значите.тыиие ,\гассивы BLOB-данных за одни раз и захотите временно отк^почнть журиа-тизашт). Если так, уберите опцтпо WITH LOG, и в журнал Т1ипзакцт булу- .записываться тол1ЖО опера-luin выделения экстентов. Битовый тип данных Битовые столбцы и пере.метп1ыс .\f017T и.мень то.аько три значения: О, 1 или NULL. Биты хранятся группа.ми но boccnhj, как 6ai[Ti)i, так что ес;нг у вас нх меньше восьми, для их хранения понадобится только (днн байт. Битовые столбцы не .могут служить индексны\ги ключахги, и по довольно убедительной причине. Столбец, ограниченный тремя возможны.мн значетгя.мн, будет очень плохим индексо.м, пото.му что не может и.меть высокую селективность. Другн.мн словами, он пе слишко.м но.может ндентпфикацни отдельных записей в большой группе (селективность индекса - количество загшсей, которые идентифицируются одним из значений ключа). В таблице с битовым столбцом и 9000 записей, с любым распределепие.м возможных значений битового столбца, наилучшей селективностью, которую сможет обеспечить индекс, построенньи ! по этому столбцу, будет одна треть всех зшшсей, или 3000 sannceii на значение к..иоча. Это означает, что запросу, испо;[Ьзующе.\[у этот птгдекс, придется прос.\ютреть 3000 загшсей, чтобы найти необходи.мую, - не са.мад оптимальная ситуацгш. SQL Ser\er предоставляет .М1южеств() операторов л.тя работы с битовыми зна-чення.\гн, битовы.\[и .масками и последовательностями битов (bitmap). Последовательность битов - это столбец или переменная, и.меюшие тип, отличный от битового, храняшие массггв битов - их последовательность (тар). Битовая .маска - это коллекция битов, обычно в фор.ме целого числа. Часто она используется для манипуляции с битами в последовательности битов. Вот пример: SELECT LEFT(name.30) AS СВ. SUBSTRING(CaSE status 8, 1 WHEN 0 THEN ELSE .autoclose END+ Case status & 4 WHEN 0 THEN ELSE .select into/bulk copy END+ CASE status & 8 WHEN 0 THEN ELSE .trunc, log on chkpt END+ CASE status & 16 WHEN 0 THEN ELSE ,torn page detection ENO+ CASE status & 32 WHEN 0 THEN ELSE ,loading END-CASE status & 64 WHEN 0 THEN ELSE ,pre-recovery END+ CASE status & 128 WHEN 0 THEN ELSE ,recovering END<-CASE status & 256 WHEN 0 THEN EuSE ,not recovered END* CASE status & 512 WHEN 0 THEN ELSE .offline END+ CASE status & 1024 WHEN 0 THEN ELSE .read only END+ CASE status & 2048 WHEN 0 THEN ELSE ,dbo use only END+ CASE status & 4096 WHEN 0 THEN ELSE ,single user END+ CASE status & 32768 WHEN 0 THEN ELSE .emergency mode END+ CASE status & 4194304 WHEN 0 THEN ELSE ,autoshrink END+ CASE status & 1073741824 WHEN 0 THEN ELSE ,cleanly shutdown END+ CASE status2 8, 16384 WHEN 0 THEN ELSE ,ANSI NULL default END+ CASE status2 & 65536 WHEN 0 THEN ELSE ,concat NULL yields NULL ENDt CASE status2 & 131072 WHEN 0 THEN ELSE ,ecursive triggers end+ 1 ... 4 5 6 7 8 9 10 ... 55 |
© 2004-2024 AVTK.RU. Поддержка сайта: +7 495 7950139 в тональном режиме 271761
Копирование материалов разрешено при условии активной ссылки. |