Разделы
Публикации
Популярные
Новые
Главная » Оптимизация производительности transact

1 ... 3 4 5 6 7 8 9 ... 55

USE master GO

IF 0BJECl IDCsp bOjndex difcr(.-rce IS \CT VJLL DROP PROG sp soundex dif-erence

CREATE PROCEDURE sp souncex c;rfe-wce =::,Гм,у: .а'-сг.ам5.>:. Pstnng2

varchar(50)-NULL, diference irt-.UlL CUTjt

Объект: sp S0unde/ Cifferer.ce

Описание: Возврашаег разницу мемау sour.dox-4C/ia ; дзу/ строк

Использование: SD soundex di fference Jstringl-epsa строка, gslr:Пс2=вторая строка,

@difference Оитрит=це,10числе .ая раз.мица .чеж:у стоок.зми Returns: Число, показывающее степень схс-кести -- 4=идентичнь1, С=полностью оазличаются Создатель: Ken Henderson, Email: kneny.hcn.com Версия: 7.0

Пример: sp soundex a1fference Rodgers Rogers

Дата создания: 1998-05-15. Последн/е изменен/я: 1998-05-16.

IF ((astnngl = /?) GOTO !:ep DECLARE texl varchar(5), (asx2 varchar (5; EXEC sp scur,dex aTphd (Bstringl, Psxl Ourpi;! EXEC sp soundex alpha gstring2, ?sx2 OUTFU! RETURN CASE

WHEN (asxl=9sx2 THEN 4

WHEN LEFT((asxl,3)=LEFT((asx2,3) THEN 3

WHEN LEFT(@sxl,2)=LEFT((asx2,2) THEN 2

WHEN LEFT((asxl,l)=LEFT(@Sx2,l) IHEN 1

ELSE 0

END Help:

EXEC sp usage (aobjectname=sp sounoex d-,fference, CcesLReturns the difference between the soundex codes of two strings,

(apanameters-(astningl=first string to translate, (astning2=second stning to tnanslate, Mifference OUTPUT=diffenence between the two as an integen,

(aretunns=An integer repnesenting the degree of similarity -- 4=1denl1cai. O=completely different,

(aauthor=Ken Hendenson. (aemail = khen@ichen,com, Matecreated 19980515, @datelastchanged=19980516, (aversion-?, (arevision =0,

(aexample=sp soundex difference Rodgers , Rogers RETURN -1

Xp sprintf

Подобно обычным храии.мы.м процедурам, расширенные храни.мые процедуры применяются так, как если бы они были отко.\ии1лнрованны\и1 програ.ммами на SQL. На самом деле расширенные храни.чпяе процедуры написаны не на Transact-SQL - они находятся в DLL (Dynamic Link Libraries), внешних по отношению к серверу. Они используют SQL Server ODS (Open Data Services) API и со.зда-ются с по.мощью языков, способных создавать DLL, таких как С++ или Delphi.

Как вы, наверное, и гюдумаан, расширенная хранимая процедура xp sprintf работает подобно функции sprintfO языка С. Можно передать eir переменную, строку фор.матирования и список api-у.ментов для со.здания строковой переменной.



В настоящее время поддерживаются только строковые аргументы, так что вы не можете передавать ей целые или другие типы данных напрямую, но вы можете применить их, преобразовав сначала в строки. Вот пример, иллюстрирующий использование xp sprintf:

DECLARE @Line varchar(80). @Title varcharOO). @Artist varcharOO) SET @Title=Butterflies and Zebras SET @Artist-Jimi Hendrix

EXEC xp sprintf @Line output.Is sang Is.@Art1st.@Title SELECT @Line

Вот пример, показывающий, как преобразовать переменные и поля других типов к строка.м, чтобы использовать их в качестве аргументов xp sprintf:

DECLARE (ciTotalMsg varchar(80). (aitems varchar(20) SELECT @Items=CAST(count(*) as varchar(20)) FROM ITEMS

EXEC master. .xp sprin.tf @TotalMsg outpJt,There were %s items on file,@Items PRINT @TotalMsg

Xp sscanf

Xp sscanf обратна xp sprintf. Вместо того чтобы помещать переменные в строку, xp sscanf извлекает значения из строки н помещает их в пользовательские переменные, подобно функции sscanfO языка С:

DECLARE @sl varchar(20),@s2 varchar(20),@s3 varchar(20).@s4 varchar(20).

@s5 varchar(20).@s6 varchar(20),@s7 varchar(20).@s8 varchar(20).

@s9 varchar(20).@slO varchar(20),@sll varchar(20).@sl2 varchar(20)

EXEC master..xp sscanf

He Meditated for a Moment. Then Kneeling Over and Across the Ogre . King Arthur Looked Up and Proclaimed His Wish : Now, Miserable Beasts That Hack The Secret of the Ancient Code And Run the Gauntlet. Today I Bid You Farewell. He stated for a Moment. Then Kneeling Xcver and AXcross the OgXs . King Arthur Looked Xcp and Proclaimed His %s : Now. Xs Beasts That Xs The Secret Xs the Xcncient %s And Xcun the Gauntlet. Today I Bid Your Farewell, @sl OUT. @s2 OUT. @s3 OUT. @s4 OUT. @s5 OUT. @s6 OUT. @s7 OUT. @S8 OUT, @s9 OUT. @slO OUT. @sll OUT. @sl2 OUT SELECT ?sl+@s2+@s3+(as4+? +@s5+ +@s6+. +(as5+ +@s7+ +@s8+ +@s9+ +@slO+ @sll+@sl2

В данном примере происходит разбор строки, заданной в первом параметре процедуры на основе спецификаторов %s и %с, которые передаются во втором параметре процедуры, в отдельные выходные символьные параметры'. Спецификатор %s выделяет строку, тогда как %с соответствует одному символу. По мере того как каждая строка или символ выделяются, они последовательно помепщ-ются в выходные переменные. Функции xp sscanf можно макси.мально передать 50 выходных переменных. Вы можете выполнить этот запрос (как и другие запросы из этой главы, он также находится на компакт-диске, прилагаемом к книге), чтобы увидеть, как работает xp sscanf.

Если вы ранее уже использовали функцию sscanf() языка С, вы будете разочарованы ограниченностью ее Transact-SQL версии. Большинство параметров форматирования, поддерживаемых sscanf() - включая спецификаторы ширины (width), - не поддерживаются, так же как и типы данных, отличные от строк.

Спецификатор %с является недоку.мсптироваишлм и работает только п оригинальной версии SQL Server (без ссрвиспаков). - Примеч. перев.



Несмотря на это xp sscanf может быть очень удобна д.тя некоторых тнноп синтаксического разбора.

Маски

Используя функцию PATINDEXO, пы .можете производить поиск в строковых полях и переменных, при.меняя групповые символы.

DECLARE @Sor,g varchar(80)

SET (aSong=Being For The Benefit Of Mr. Kite;

SELECT PATlNDEXCIKitr .(aSong)

В TaKo.vi контексте PATINDEX() работает очень похоже на предикат LIKE иред-;южения WHERE. Основное различие состоит в том, что PATINDEX() - больше, чем просто предикат; эта функция также возвращает смещение найденного образца, чего не делает LIKE. Чтобы увидеть, насколько похожи PATINDEX() и LIKE, взгляните на эти примеры;

SELECT * FROM authors WHERE PATINDEX(СгеепГ ,aujname)<>0

можно переписать как

SELECT * FROM authors WHERE aujname LIKE GreenV

Аналогично,

SELECT title FROM titles WHERE FATINDEX(IdataDase.notes)<>0 можно переписать с использованием

SELECT title FROM titles WHERE notes LIKE XdatabaseV

PATINDEXO становится по-настоящему полезной, когда вам необходи.мо отфильтровать записи не только по наличию маски, но и по ее местоположению.

SET NOCOUNT ON

CREATE TABLE #testblob (Cl text DEFAULT )

INSERT #testb1ob VALUES (Golf is a good wak spoiled)

INSERT #testblob VALUES (Now is the time for all good men)

INSERT #testblob VALUES (Good Golly. Miss Molly!)

SELECT *

FROM #testblob

WHERE cl LIKE Igoodr

SELECT *

FROM #testblob

WHERE PATINDEX(IgoodX,cl)>15 GO

DROP TABLE #testblob cl

-Golf Is a good walk spoiled Now 1S tne time for all good men Good Golly. Miss Molly!

Now IS the time for all good men

В данном случае первый запрос вернул все записи таблицы, пото.му что LIKE не может отличить одно появление образца от другого (конечно, вы .могли бы



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

Выполнение строк

Функция Transact-SQL ЕХЕС() и хранимая процедура sp executesql позволяют выполнить команду SQL, находящуюся в строковой переменной. Эта мопцгая функция позволяет создавать и выполнять запросы с использование.м условий выполнения из хранимой процедуры или пакета команд Transact-SQL. Вот пример запроса, создающего перекрестную таблицу (cross-tab) во времени выполнения, на основе записей из таблицы pubs..authors:

USE pubs

IF OBJECT IDCauthor crosstab) IS NOT NULL DROP PROC author crosstab

CREATE PROCEDURE author crosstab AS

SET NOCOUNT ON

DECLARE @execsql nvarchar(4000). gAuthorName varchar(80)

-- Инициализируеи строку со сценариев создания

SET @execsql=CREATE TABLE Flautxtab (Title varchar(80)

SELECT (aexecsql=(aexecsql + .[+au fname+ +au lname+] chard) NULL DEFAULT

FROM authors

EXEC((aexecsql + ))

DECLARE InsertScript CURSOR FOR

SELECT execsql=INSERT #autxtab (Title.+[+a.au fname+ +a.au lname+]) VALUES ( +t.title+ , X )

FROM titles t JOIN titleauthor ta ON (t.title id=ta.titlejd) JOIN authors a ON (ta.aj id=a.au id) ORDER BY t.title

OPEN InsertScript ,

FETCH InsertScript INTO (execsql WHILE ((a(aFETCH STATUS-=0) BEGIN

EXEC sp executesql (execsql

FETCH InsertScr-ipt INTO Oexersnl

CLOSE InsertScriDt DEALLOCATE InsertScript SELECT * FROM ##autxtab DROP TABLE ##autxtab GO

EXEC author crosstab GO

(результаты сокращены)

Title Abraham Bennet Reginald Blotchet-H

But Is It User Friendly?

Computer Phobic AND Non-phobic Individuals: Benavior Variations Computer Phobic AND Non-Phobic Individuals: Behavior Variations Cooking with Computers; Surreptitious Balance Sheets Cooking with Computers; Surreptitious Balance Sheets



Emotional Securvcy. А Alyoruniri Fifty Yeans in Buckingham Palace Kitchens X

Is Anger the Enemy? Is Anger the Enemy? Life Without Fear Net Etiquette

Onions. Leeks, and Garlic: Cooking Secrets of the MeGiterrdrean

Prolonged Data Deprivation: Four Case Studies

Secrets of Silicon Valley

Secrets of Silicon Valley

Silicon Valley Gastronomic Treats

Straight Talk About Computers

Sushi. Anyone?

Sushi. Anyone?

Sushi, Anyone?

The Busy Executives Database Guide The Busy Executives Database Guide X

The Gourmet Microwave The Gourmet Microwave You Can Combat Computer Stress!

Перекрестная таблица, создаваемая этим запросом, состоит из одиогс ца для названия kihifh (ио OflHONjy для каждого авгора). X обозначчрх пересечение название-автор. Гак как список авторов может вре.мд .j, изменяться, не существует способа заранее узнать, какие столбцы будет'имть таблица. Вот почему нам приходится прп.меиять дина.чтческий SQL для ее Дания.

В данном коде использовано несколько интересных решений. Во-первых об

ратите внимание па часть кода, нри.меняе.\!У10 для начального thnn,.. V. , Pмиpoвaния

строковой пере.\!еннон @execsql:

SET (aexecsqbCREATE TABLE ##autxtab (Title varchar(8G)

SELECT (aexecsql-(aexecsql + .[+au fname +aujname+] char(l) NULL DEFAULT .....

FROM authors

Перекрестная таблица, возвращаемая этим занросо.м, сначала форм i-j-.

во временной таблице. @execsql служит для создания и заполиециу РУ

.. этой тао-

тот код создает @execsql, инициализируя ее заготовкой ддд оман ы

CREATE TABLE, а зате.м добавляются определения новых столбцпп

г , .. < каждой

записи из таблицы authors. 1акоп спосоо создания @execsql - довольно бт

и позволяет избежать применения курсоров - механиз.ма обработки табтиц но

одной записи за раз. По сравнению с ко.\ганда.\ги для работы с множествами

курсоры - ие слишком эффективный .механргз.м, вы должны избегать их п'

менения всегда, когда это возможно (см. главу 13, Курсоры ). Когда SELECT за

канчивает свой цикл по таблице authors table, (Sexecsql напо.\нигает след ющее-

CREATE TABLE ##autxtab (Title varchar(80).

[Abraham Bennet] chard) NULL DEFAULT .

[Reginald Blotchet-HalIs] char(l) NULL DEFAULT ,

[Cheryl Carson] chard) NULL DEFAULT ,

[Michel DeFrance] chard) NULL DEFAULT .

[A<uo Yokomoto] chard) NULL DEFAULT



Едилствепное, 4eio здесь не хватает, - закрьнзаклцен скобки, которая добавляется, когда ЕХЕС() вызывается для создания таблицы:

EXEC((aexecsql-))

Для выполнения @execsql в данном случае можно заде11СТБ0пагь как ЕХЕС(), так и sp executesqL Вообще говоря, sp executesql - более быстрьи'! и более функ-цнональньп ! способ, чем ЕХЕС(). Когда вам необходимо вьнюлнять дтнгампчески сгенерированный SQL несколько раз подряд (когда ,\!ежду запуска.чш изменяются только параметры запроса), остановите свои выбор на sp executesqL Этот \!етод позволяет повторно прнл!енить план выполнения, сгенерированный оптимизатором запросов при первом выполнении запроса. Он более эффективен, чем ЕХЕС(), потому что строка запроса создается только один раз и каждый пара-.метр указывается в его родном формате, а не преобразуется сначала к строке, как это требуется для ЕХЕС().

Sp executesql позволяет помещать параметры в текст запроса, используя стандартные названия переменных в качестве меток-заполнителей, вот так:

sp executesql NSELECT * FROM authors WHERE au lname LIKE @au lna(i;e.

N@au lname varchar(4C) .@au lnanie=Green*

Здесь @aujname - это .метка-заполиптель. Хотя запрос может выполняться несколько раз подряд, от выполнения к выполнению меняется лишь значение @au lname. В результате очень вероятно, что оптимизатор запросов сможет избежать пересоздания плана выполнения каждый раз, когда запрос выполняется.

Обратите вни.мапие на использование префикса N , для обозначения того факта, что символьные строки передаются процедуре в кодировке Unicode. Lni-code рассматривается подробнее позже в этой главе, но важно от.метнть, что для sp executesql требуются строки в кодировке Unicode. Вот почему @execsql объявлена как nvarchar.

В данном конкретном случае при.менение ЕХЕС() предпочтительнее, чем sp executesqi, по двум причтшам: она не вызывается цнклтгческн пли несколько раз подряд и позволяет осуществлять простую конкатенацию строк внутри списка параметров; sp executesql, как н все храни.мые процедуры, этого не может.

Вторая часть процедуры иллюстрирует более сложное при.менение динамического SQL. Для того чтобы пометить каждое пересечение название-автор си.мволом Х?>, запрос должен динамически со.здать оператор INSERT для каждой пары название-автор. Название становится добавляемым значением, автор становится названием столбца, а X - его значением.

В отличие от предыдущего при.мсра, для выполнения динамически сгснерп-роваиного оператора INSERT применяется sp executesql, потому что он вызывается несколько раз подряд; благодаря конкатенации при декларации курсора нет необходимости в конкатенации пара.метров.

Так как sp executesql позволяет помещать пара.метры в строку запроса, вы, возможно, спросите, почему мы используем эту воз.\ншность для передачи столбцов из таблицы. В конце концов, они кажутся отличны.м примеро.м параметров запроса, которые изменяются между запусками, - зачем все эти конкатенации в курсоре? Причина в том, что в sp executesqi в качестве подставляемых пара.метров можно задействовать только настоящие параметры - вы пе можете за.менять



части строки запроса без разбора. 15ы .\и)жете pacruj;iai-aTb за.\1еняе.\иле пара.мет-ры в любо.м .месте, где можно использовать обычные переменные, если запрос будет нор.мально выполняться (вне sp executesql), но вы не .можете за.меиять ключевые слова, названия объектов или названия столбцов с по.мощью меток-занолиителей: sp executesql ие будет подставлять их при вынолненпн запроса.

Одно, последнее, замечание относительно причины, по которой мы при.меняе.м глобатьные временные таблицы. Глобальная временная таблица - это временная таблица, и.мя которой начинается с префикса ## в.место # и которая видима всем соединения.м, а ие только то.му, в которо.м она была создана. Как и в случае с лока-тьны.ми временными таблицами, глобальные временные таблицы уничтожаются, когда они больше не используются (когда отк-тючается последнее задействующее таблицу соединение).

Здесь это необходи.мо, потому что \\ы испо.тьзуе.м динамический Transact-SQL для создания перекрестной таблицы, а локальные временные таблицы, созданные динамически, видн.мы только ЕХЕС() или sp executesql, которые нх создали. На са.мо.м деле они удаляются, как только заканчивает выполняться динамический SQL, создавший их. Так что вместо локальных мы при.меняе.м глобальные временные таблицы, и они остаются види.мы, пока ие будут явно уничтожены запросо.м или пока ие закроется соедииеиие

Са.мый большой недостаток глобальных вре.ме1Н1ЫХ неремен1плх по сравнению с локальныли! - возможный конфликт названий. В отличие от их лока1ь-ных собратьев названия глобальных локальных таблиц не уникальны для всех соединений - за счет .этого omi и становятся доступны глобально. Независимо от того, сколько соединений ее псиользуют, таблица ##autxtab соответствует Т0Ч1Ю одному объекту в базе данных tempdb. Если соединение попытается создать глоба-тьную временную таблицу, которую уже создато другое соедине>н1е, попытка создания завершится неудачей.

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

Во-вторых, мы можем создать саму таблицу в главном запросе, а затем применить Transact-SQL для выполнения оператора ALTER TABLE. Это требуется при 1юстепенпом добавлении столбцов для каждого автора. Вот вариация предыду-1цей процедуры, которая выполняет то же са.\юе:

CREATE PROCEDURE author crosstab2 AS

SET NOCOUNT ON

DECLARE laexecsql nvarchar(4000), CaAuthorNaaie varchar(80) CREATE TABLE #autxtab (Title varchar(80)) DECLARE AlterScnpt CURSOR FOR

SELECT ALTER TABLE #autxtab ADD [-i-au frai!ie-i- -aulname] chard) NULL DEFAULT FROM authors FOR READ ONLY OPEN AUerScript FETCH AlterScript INTO gexecsql WHILE ((a(aFETCH STAruS=0) BEGIN EXEC sp executesql (aexecsql



FETCH AlterScript INTO ?exec5ql

CLOSE AlterScript DEALLOCATE AlterScrrpt

DECLARE InsertScript CURSOR FOR

SELECT execsql = INSERT #autxtab (Title, + [+a,au fnai)ie+ +a.au iname+]) VALUES ( +t.titles . X )

FROM titles t JOIN titleauthor ta ON (t.tille ic; ta,titlc id) JOIN authors a 0.\ (ta au id=a.aj iai ORDER BY t,title

OPEN InsertScript

FETCH InsertScript INTO Pexecsql

WHILE ((a(aFETCHjTAlUS-0) BEGIN

EXEC sp executesql Oexecsql

FETCH InsertScript INTO laexecsql

CLOSE InsertScript DEALLOCATE InsertScript

SELECT * FROM #autxtab OROP TABLE #autxtab

Обратите внимание на иснользование курсора AlterScript для выполнения запросов ALTER TABLE с иомошыо sp executesql. Поскольку са.ма таблица создается в главно.м запросе, а временные объекты со.зда10тся в это.м же запросе и видимы динамическим запроса.м, мы може.м задействовать локальные временные переменные и те.м самым избежать конфликтов имен. Хотя для этого решения требуется больше кода, чем для первоначального, оно бе\зопаснее.

Обратите внимание на то, что это касается только объектов, а не локальных переменных. Пере.метшю, объявленные в вызванно11 процедуре, не В1шимы ЕХЕС() или sp executesql. Так же как неременные, объявленные в ЕХЕС() или в вызов sp executesql, выходят из области видн.мости, когда возвращаются вызывающей стороне. Единственный способ передачи переменных между ними - использование списка параметров sp executesql или конкатенации внутри вызова EXEC.

Unicode

в прошлом строковые данные были ограничены снлпюлами из множества, состоящего из 256 символов. Каждьп! сн.мво.т состоял из одного байта, а байт может хранить только 256 (2 ) различных си\шолов. До припяттш стандарта Unicode все символьные .\нюжества составлялись из однобайтовых си.мволов.

Unicode расширяет количество воз.можных сн,\шолов до 2 или 65536 с по-.мощью использования двух байтов для представления символов вместо одного. За счет этого увеличенного объема можно использовать алфавиты и символы из больштшства языков мира, включая и однобайтовые множества, применявшиеся ранее.

Обычные строковые типы Transact-SQL (char, varchar и text) тшпользуют символы из обычного одиобаптового набора символов. Этот набор cи^шoлoв выбирается во вре.мя инсталляции и не может быть изменен впоследствии без пересоздания базы данных и перезагрузки данных. Unicode-строки мот-ут хранить



любые символы, определенные в станларк; Unicode. Так как сгрока.м Unicode по сравнению с обычиы.\И1 строкахш иеоб.чоди.чи) вдвое бо;и^ше места для хранения, их длина .\южет быть только 4000 сн.мволов.

В SQL Server существуют специальные типы данных для хранения строк в кодировке: nciiar, nvarchar и ntext. Вы можете прп.менять ути типы данных для тех столбнов, в которых необходи.мо хранить символы и; нескольких си.мволь-ных .множеств. Как и в случае обычных строковых nojieii, используйте nvarciiar, если длина данных из.меняется от строки к строке, и nciiar - если нет. Задействуйте ntext, если вам необходи.мо хранить больше 4 ООО си.мволов.

Строки Unicode SQL Server основываются на типах данных SQL-92 National Character. Как и SQL-92, в Transact-SQL используется символьный префикс N, чтобы отличать типы данных и значения Unicode, наподобие этого:

SELECT DA:-ALENGTH(NThe Firm)

Этот запрос вернул 16 , так как N в верхнем регистре делает The Firm строкой в кодировке Unicode.

Числовые типы

Transact-SQL поддерживает четыре основных [сласса числовых данных: float и real, numeric и decimal, money и smallmoney, и целые тины (int, smallint и tinyint). Float и real - типы с плавающей занято!! - это приблизительные, неточные типы -некоторые значения из их диапазонов (-1,79Е 308 до 1,79Е + 308 и -3,40Е + 38 до 3,40Е + 38 соответственно) ие .могут быть представлены точно. Numeric и decimal - числовые типы с фиксироваппоп занятой, с установленно!! пользователем, фиксироваиной точностью и раз.мерностью, эти типы имеют диапазон от -10 - 1 до -FlQ-* - L Типы money и smallmoney служат для представления денежных величин и имеют диапазоны от -2 до +2- - 1 и -2 до -i-2- - 1 с размерностью, равной четырем (от -214 748.3648 до -(-214 748,3647 соответственно).

Целые типы пргьменяются для представления целых чисел. Тип данных int занимает четыре байта и .может представлять целые зиачеиия от -2- до -)-22- - 1. Smallint зани.мает два б;шта и может представлять пелые чиоча от -2 до +2- - 1. Tinyint использует только одни байт и южeт хранить целые числа между О и 255,

Шутки с плавающей запятой

При работе со значениями с нлавающе!! занятой вы прежде всего обнаружите, что Transact-SQL некорректно работает с ошибками, связанными с округлением значений с плавающей запятой. Из-за этого одна и та же численная задача, представленная разными способами, может возвращать разные результаты - нонсенс согласно законам математики. Языки, в которых обработка ошибок округления не реализована должным образом, особенно восприимчивы к ошибкам из-за различий при упорядочивании. Вот при.мер, которьи1 генерирует список случайных значений с плавающей запятой, а затем по-разному их упорядочивает и вычисляет их сумму:



SET NOCOUNT ON CREATE TABLE #rand (kl int identity, cl float DEFAULT (

(CASE (CAST(RAND()+.5 AS int)*-l) WHEN 0 THEN 1 ELSE -1 END)*(C0NVERT(1nt,

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 Irano. #rand2. #rand3

2337,1234806786265

6133,8947556398543

4661,8483968063565

-487.1674384075381

5402.6488177346673

8548.8042443202648

1151.1290584163344

1983.5178142724058

-48.855436548423761

865.11748910633833

19742,753545549555 19742.763546549551

19742.763546549551

Так как во всех трех случаях суммируются одни и те же числа, результаты должны быть одинаковыми, однако это не так. Увеличение точности SQL Server при работе с плавающей запятой (с помощью параметра командной строки сервера - /р) может помочь, но не решит проблему - опгабки округления не обрабатываются корректно независимо от точности. Это вызывает серьезные проблемы для приложений, зависящих от точности значений с плавающей запятой, и это основная причина, по которой вы будете часто видеть сложные вычисления



1 ... 3 4 5 6 7 8 9 ... 55
© 2004-2024 AVTK.RU. Поддержка сайта: +7 495 7950139 в тональном режиме 271761
Копирование материалов разрешено при условии активной ссылки.
Яндекс.Метрика