
RUS_-_Karejev_-_Razrabotka_Windows-prilozhenij
.pdfthis.Controls.Add(this.txbSubject);
this.Controls.Add(this.txbBlindCopy);
this.Controls.Add(this.txbCopy);
this.Controls.Add(this.txbTo);
this.Controls.Add(this.lblAttachNumber);
this.Controls.Add(this.lblAttachments);
this.Controls.Add(this.pblAttachments);
this.Controls.Add(this.btnSend);
this.Controls.Add(this.lblBody);
this.Controls.Add(this.lblSubject);
this.Controls.Add(this.lblBlindCopy);
this.Controls.Add(this.lblCopy);
this.Controls.Add(this.lblTo);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "SendMessage";
this.Text = "Отправка сообщения";
this.WindowState = System.Windows.Forms.FormWindowState.Maximized; this.ResumeLayout(false);
}
#endregion
private void btnViewAttach_Click(object sender, System.EventArgs e)
{
if(oFDAttach.ShowDialog() != DialogResult.OK) return;
txbAttach.Text = oFDAttach.FileName;
}
private void btnAddAttach_Click(object sender, System.EventArgs e)
{
MailAttachment attach = new MailAttachment(oFDAttach.FileName); message.Attachments.Add(attach);
txbAttach.Text = ""; oFDAttach.FileName = String.Empty; this.AddAttachmentsToPanel();
}
private void AddAttachmentsToPanel()
{
pblAttachments.Controls.Clear();
for(int i = message.Attachments.Count -1; i >= 0; i--)
{
MailAttachment attach = (MailAttachment)message.Attachments[i]; Label lblNumber = new Label();
Label lblAttachName = new Label(); lblNumber.Text = String.Format("#{0}", i + 1); lblAttachName.Text = attach.Filename;
lblAttachName.TextAlign = lblNumber.TextAlign = ContentAlignment.MiddleLeft; lblAttachName.Anchor = lblNumber.Anchor = AnchorStyles.Top | AnchorStyles.Left;
lblNumber.Location = new Point(15, i*25); lblAttachName.Location = new Point(50, i*25); lblNumber.Size = new Size(20, 20); lblAttachName.Size = new Size(500, 20);
lblNumber.ContextMenu = lblAttachName.ContextMenu = contextMenuDeleteAttach; lblNumber.Tag = lblAttachName.Tag = i; pblAttachments.Controls.Add(lblNumber); pblAttachments.Controls.Add(lblAttachName);
}
}
private void itemDeleteAttach_Click(object sender, System.EventArgs e)
{
MenuItem item = (MenuItem)sender; ContextMenu menu = (ContextMenu)item.Parent; Label source = (Label)menu.SourceControl; object o = source.Tag;
int i = Int32.Parse(o.ToString()); message.Attachments.RemoveAt(i); this.AddAttachmentsToPanel();
}
private void btnSend_Click(object sender, System.EventArgs e)
{
message.BodyFormat = MailFormat.Text; message.Body = txbBody.Text; message.Cc = txbCopy.Text; message.Bcc = txbBlindCopy.Text; message.Subject = txbSubject.Text; message.To = txbTo.Text;
message.From = ((UserIdentity)Thread.CurrentPrincipal.Identity).Mail;
Mail.MailSender mailSender = new Mail.MailSender(((UserIdentity)Thread.CurrentPrincipal.Identity).Smtp); mailSender.Send(message, ((UserIdentity)Thread.CurrentPrincipal.Identity).Password); MessageBox.Show("Ваше сообщение отправлено.");
this.Close();
}
}
}

Листинг 3.26.
ФормапросмотрасообщенийViewMessage.cs
В эту форму загружается сообщение для чтения при его выборе из списка формы MessageList. Значения свойства Name элементов управления приведены на рис. 3.35.
увеличить изображение
Рис. 3.35. Форма ViewMessage
Полный листинг формы:
using System;
using System.Drawing; using System.Collections;
using System.ComponentModel; using System.Windows.Forms;
namespace MailApplication
{
///<summary>
///Summary description for ViewMessage.
///</summary>
public class ViewMessage : System.Windows.Forms.Form
{
///<summary>
///Required designer variable.
///</summary>
private System.ComponentModel.Container components = null;
private System.Windows.Forms.Label lblAttachments; private System.Windows.Forms.Panel pblAttachments; private System.Windows.Forms.Label lblBody; private System.Windows.Forms.Label lblSubject; private System.Windows.Forms.Label lblCopy; private System.Windows.Forms.Label lblMessageBody; private System.Windows.Forms.Label lblFrom; private Mail.Message message;
public ViewMessage(Mail.Message msg)
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
this.message = msg;
}
///<summary>
///Clean up any resources being used.
///</summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
///<summary>
///Required method for Designer support - do not modify
///the contents of this method with the code editor.
///</summary>
private void InitializeComponent()
{
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(ViewMessage)); this.lblAttachments = new System.Windows.Forms.Label();
this.pblAttachments = new System.Windows.Forms.Panel(); this.lblBody = new System.Windows.Forms.Label(); this.lblSubject = new System.Windows.Forms.Label(); this.lblCopy = new System.Windows.Forms.Label(); this.lblFrom = new System.Windows.Forms.Label(); this.lblMessageBody = new System.Windows.Forms.Label(); this.SuspendLayout();
//
//lblAttachments
this.lblAttachments.Location = new System.Drawing.Point(24, 280); this.lblAttachments.Name = "lblAttachments";
this.lblAttachments.Size = new System.Drawing.Size(64, 23); this.lblAttachments.TabIndex = 29;
this.lblAttachments.Text = "Вложения:";
this.lblAttachments.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//pblAttachments
//
this.pblAttachments.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right))); this.pblAttachments.AutoScroll = true; this.pblAttachments.Location = new System.Drawing.Point(128, 280); this.pblAttachments.Name = "pblAttachments"; this.pblAttachments.Size = new System.Drawing.Size(544, 178); this.pblAttachments.TabIndex = 28;
//
//lblBody
this.lblBody.Location = new System.Drawing.Point(24, 96); this.lblBody.Name = "lblBody";
this.lblBody.TabIndex = 26; this.lblBody.Text = "Текст сообщения:";
this.lblBody.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//lblSubject
//
this.lblSubject.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right))); this.lblSubject.AutoSize = true;
this.lblSubject.Location = new System.Drawing.Point(352, 16); this.lblSubject.Name = "lblSubject";
this.lblSubject.Size = new System.Drawing.Size(35, 16); this.lblSubject.TabIndex = 24;
this.lblSubject.Text = "Тема:";
this.lblSubject.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
//lblCopy
this.lblCopy.AutoSize = true;
this.lblCopy.Location = new System.Drawing.Point(24, 56); this.lblCopy.Name = "lblCopy";
this.lblCopy.Size = new System.Drawing.Size(40, 16); this.lblCopy.TabIndex = 20;
this.lblCopy.Text = "Копия:";
this.lblCopy.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//lblFrom
//
this.lblFrom.AutoSize = true;
this.lblFrom.Location = new System.Drawing.Point(24, 24); this.lblFrom.Name = "lblFrom";
this.lblFrom.Size = new System.Drawing.Size(47, 16); this.lblFrom.TabIndex = 18;
this.lblFrom.Text = "От кого:";
this.lblFrom.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// lblMessageBody
//
this.lblMessageBody.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right))); this.lblMessageBody.Location = new System.Drawing.Point(136, 96); this.lblMessageBody.Name = "lblMessageBody";

this.lblMessageBody.Size = new System.Drawing.Size(536, 176); this.lblMessageBody.TabIndex = 30;
//
// ViewMessage
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(694, 476); this.Controls.Add(this.lblMessageBody); this.Controls.Add(this.lblAttachments); this.Controls.Add(this.pblAttachments); this.Controls.Add(this.lblBody); this.Controls.Add(this.lblSubject); this.Controls.Add(this.lblCopy); this.Controls.Add(this.lblFrom);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "ViewMessage";
this.Text = "Просмотр сообщения";
this.Load += new System.EventHandler(this.ViewMessage_Load); this.ResumeLayout(false);
}
#endregion
private void ViewMessage_Load(object sender, System.EventArgs e)
{
lblMessageBody.Text = this.message.Text; lblCopy.Text += this.message.CC; lblSubject.Text += this.message.Subject; lblFrom.Text += this.message.FromEmail;
}
private void AddAttachmentsToPanel()
{
pblAttachments.Controls.Clear();
for(int i = message.Attachments.Length -1; i >= 0; i--)
{
//MailAttachment attach = (MailAttachment)message.Attachments[i]; Mail.AttachDescriptor attach = this.message.Attachments[i];
Label lblNumber = new Label(); Label lblAttachName = new Label();
lblNumber.Text = String.Format("#{0}", i + 1); lblAttachName.Text = attach.Name;
lblAttachName.TextAlign = lblNumber.TextAlign = ContentAlignment.MiddleLeft; lblAttachName.Anchor = lblNumber.Anchor = AnchorStyles.Top | AnchorStyles.Left; lblNumber.Location = new Point(15, i*25);
lblAttachName.Location = new Point(50, i*25); lblNumber.Size = new Size(20, 20); lblAttachName.Size = new Size(500, 20);
//lblNumber.ContextMenu = lblAttachName.ContextMenu = contextMenuDeleteAttach; lblNumber.Tag = lblAttachName.Tag = i;
pblAttachments.Controls.Add(lblNumber);
pblAttachments.Controls.Add(lblAttachName);
}
}
}
}
Листинг 3.27.
1)Точный перевод c англ. слова Wizard – "волшебник", но, следуя устоявшейся традиции, я буду использовать далее слово "Мастер".
2)Здесь и далее приводятся только те фрагменты кода, о которых идет речь в текущем разделе.
©2003-2007 INTUIT.ru. Все права защищены.

Интернет-Университет Информационных Технологий http://www.INTUIT.ru
Создание Windows-приложений на основе Visual C#
4. Лекция: Работа с данными: версия для печати и PDA
Что такое реляционная база данных? Элементы языка SQL. Агрегатные функции. Типы данных. Оператор сравнения like. Создание таблицы с помощью запросов. Команды изменения языка DML. Подключение к базе данных – технология ADO.NET. Модель объектов ADO.NET. Таблицы и поля (объекты
DataTable и DataColumn). Объекты DataRelation. Строки (объект DataRow). DataAdapter. Объекты DBConnection и DBCommand. Использование визуальной среды для работы с ADO.NET. Server Explorer. Программирование объектов ADO.NET. CommandText. СonnectionString. Управление соединением. Объект Connection. Объект Command. Вывод связанных таблиц. Связывание элементов управления с данными. Перемещение по записям. Объект CurrencyManager. Изменение записей
Для работы с данной лекцией используйте примеры.
Что такоереляционная базаданных?
Базы данных — это совокупность сведений (об объектах, процессах, событиях или явлениях), относящихся к определенной теме или задаче, которая организована таким образом, чтобы обеспечить удобное представление этой совокупности, как в целом, так и любой ее части.
Реляционная база данных представляет собой множество взаимосвязанных таблиц, каждая из которых содержит информацию об объектах определенного типа. Каждая строка таблицы содержит данные об одном объекте (например, товаре, фирме, клиенте), а столбцы таблицы содержат различные характеристики этих объектов — атрибуты (например, наименования и цены товаров, адреса и телефоны фирм или клиентов). Строки таблицы называются записями; все записи имеют одинаковую структуру — они состоят из полей, в которых хранятся атрибуты объекта. Каждое поле записи содержит одну характеристику объекта и строго определенный тип данных (например, текстовая строка, число, дата). Все записи имеют одни и те же поля, только в них содержатся разные значения атрибутов.
Для работы с данными используются системы управления базами данных (СУБД). Основные функции СУБД — это определение данных (описание структуры баз данных), обработка данных и управление данными.
Любая СУБД позволяет выполнять следующие операции с данными:
добавлять в таблицу одну или несколько записей;
удалять из таблицы одну или несколько записей;
обновлять значения некоторых полей в одной или нескольких записях;
находить одну или несколько записей, удовлетворяющих заданному условию.
Для выполнения этих операций используется механизм запросов. Результатом выполнения запросов является либо отобранное по определенным критериям множество записей, либо изменения в таблицах. Запросы к базе формируются на специально созданном для этого языке, который так и называется — язык структурированных запросов (SQL — Structured Query Language).
Важнейшей функцией СУБД является управление данными. Под управлением данными обычно понимают их защиту от несанкционированного доступа, поддержку многопользовательского режима работы и обеспечение целостности и согласованности данных.
Рассмотрим более подробно концепцию реляционных баз данных. Предположим, что вам нужно создать таблицу, содержащую информацию о товарах и поставщиках. Каждая строка этой таблицы (называемая также записью) будет соответствовать определенному порядку: каждый столбец (называемый также полем) будет содержать значение для каждого типа данных – наименования, цены, названия поставщика, представляемого в каждой строке. Таблица будет выглядеть примерно так (рис. 4.1):
увеличить изображение
Рис. 4.1. Простое занесение записей в таблицу
Это и есть основа реляционной базы данных. Конечно же, реальная таблица будет содержать гораздо большее число записей и столбцов. Однако реляционные базы почти никогда не состоят из одной таблицы. Создав несколько таблиц, связанных между собой, мы сможем выполнить более сложные и мощные операции с данными. Но зачем связывать между собой таблицы? Один поставщик может предлагать большое количество различных товаров. В результате в нашей таблице будет большое количество повторяющихся однотипных записей. Если вынесем информацию о поставщике в отдельную таблицу, то в результате получим две таблицы: в одной будет информация о товаре, в другой — информация о поставщике. Связать две получившиеся таблицы мы сможем, вводя уникальный код поставщика (ID), который будет присутствовать в обеих таблицах. Схематическая связь таблиц,
отображаемая в СУБД Microsoft Access ( входящая в комплект Microsoft Office) (рис. 4.2):
Рис. 4.2. Связь таблиц по полю "Код поставщика"

Таблицы связаны по полю "Код поставщика", причем в таблице "Поставщики" на связи указана единица, а в таблице "Товары" — знак бесконечности. Эти символы и подтверждают нашу логику: один поставщик может предоставлять большое число товаров, а подобное отношение таблиц и называется "один-ко-многим".
Сами таблицы будут выглядеть так (рис. 4.3):
увеличить изображение
Рис. 4.3. Связанные таблицы
Нажимая на знак (+), мы видим таблицу с товарами. Пользоваться связанными таблицами стало несравненно удобней, но самое главное — мы добились отсутствия повторяющихся записей. На практике, при оперировании с большими таблицами это означает экономию места на жестком диске и значительное увеличение скорости. Последний параметр является особенно важным.
Введенный столбец "Код поставщика" содержит неповторяющиеся значения для различных поставщиков. Для таблицы "Поставщики" он является первичным ключом. Первичный ключ — это столбец или комбинация столбцов, которые уникально идентифицируют запись в таблице. Аналогично, для таблицы "Товары" первичным ключом будет столбец "Код продукта".
На прилагаемом диске находится документ Microsoft Access RBProduct (Code\Glava4\ RBProduct.mdb), который содержит рассматриваемые выше примеры.
Элементы языкаSQL
SQL (обычно произосимая как "sequel") символизирует собой Структурированный Язык Запросов. Это язык, который дает нам возможность работать с данными в реляционных базах данных.
Мир баз данных становится все более и более единым, что привело к необходимости создания стандартного языка, который мог бы использоваться в большом количестве различных видов компьютерных сред. Стандартный язык позволит пользователям, знающим один набор команд, использовать их, чтобы создавать, отыскивать, изменять и передавать информацию независимо от того, работают ли они на персональном компьютере, сетевой рабочей станции или на сервере.
Элегантность и независимость от специфики компьютерных технологий, а также поддержка его лидерами промышленности в области технологии реляционных баз данных сделали SQL основным стандартным языком. По этой причине любой, кто хочет работать с современными базами данных, должен знать SQL.
Стандарт SQL определяется ANSI (Американским Национальным Институтом Стандартов), а также ISO (Международной организацией по стандартизации). Однако большинство коммерческих программ баз данных расширяют SQL без уведомления ANSI, добавляя разные особенности в этот язык, которые, как они считают, будут полезны. Иногда они несколько нарушают стандарт языка, хотя хорошие идеи имеют тенденцию развиваться и вскоре становиться стандартами сами по себе в силу полезности своих качеств.
Для обращения к базе данных используются запросы, написанные на языке SQL. Запрос — это команда, которую вы даете вашей программе базы данных, и которая сообщает ей, чтобы она вывела определенную информацию из таблиц в память. Эта информация обычно посылается непосредственно на экран компьютера или терминала, которым вы пользуетесь, хотя в большинстве случаев ее можно также послать принтеру, сохранить в файле (как объект в памяти компьютера) или представить как вводную информацию для другой команды или процесса.
Несмотря на большое количество разновидностей этого языка, существующих в настоящее время, его логика работы проста. Достаточно освоить основные команды хотя бы в одной из версий, чтобы впоследствии без труда разобраться в любой другой его реализации.
Microsoft Query Analyzer, входящий в комплект Microsoft SQL Server 2000 – отличный инструмент для изучения языка SQL. Если у вас установлен этот пакет, то можно приступать к работе. Запускаем Query Analyzer и в появившемся окне указываем следующие параметры (рис. 4.4):

Рис. 4.4. Задание параметров подключения
Мы используем подключение к серверу, находящемуся на нашем компьютере, — поэтому указываем имя сервера (local) (Можно также использовать знак точки — (.)). В других случаях – для подключения по локальной сети, например, — используйте кнопку обзора для поиска нужного сервера. Установка галочки – "Запускать SQL сервер в случае его остановки" (Start SQL Server if it is stopped) — позволяет поддерживать бесперебойную связь с сервером. Параметр Connect using задает аутентификацию при
подключении к серверу — при выбранном значении Windows authentification нет надобности вводить имя пользователя и пароль.
Если вы все сделали правильно, то появляется главное окно программы, содержащее чистый бланк для записи SQL-запросов. Добавим окно, в котором мы будем просматривать содержимое базы данных, – пункт меню Tools/Object Browser/(Show/hide) или клавиша F8. Нам также потребуется окно для отображения результатов запросов — Window/Show Results Pane (Ctrl+R). В результате получим следующее (рис. 4.5):
увеличить изображение
Рис. 4.5. Главное окно программы
Первое, что мы видим в окне Object Browser, — имя компьютера и связанного с ним сервера. На рисунке это 7EA2B2F6068D473. Это имя формируется, когда мы устанавливаем операционную систему Windows. Далее располагается древовидная структура — содержимое пакета SQL Server 2000, состоящего из баз данных master, model, msdb, NorthwindCS и tempdb. В отличие от других баз данных, обеспечивающих работу самой программы, NorthwindCS является специальной учебной базой. С ней мы и будем
работать. На панели инструментов из выпадающего списка выбираем базу, для подключения — . Можно этого не делать, но тогда в окне бланка необходимо будет каждый раз указывать строку — use NorthwindCS;. Будем полагать в дальнейшем, что на панели инструментов определена база данных NorthwindCS;.
Итак, напишем первый запрос1) и нажмем клавишу F5 (пункт меню Query —>Execute):
select * from Customers;
В результате возвращаются все записи из таблицы Customers базы данных NorthwindCS. Для просмотра содержимого базы данных
используем Object Browser, щелкая на знак (+) возле соответствующего объекта. Переключившись на вкладку , видим сообщение, означающее, что была извлечена 91 запись:
(91 row(s) affected)
Главное окно программы принимает следующий вид (рис. 4.6):

Рис. 4.6. Запрос извлек таблицу Customers
Вы можете менять вид данных, отображаемых на панели результатов: пункт меню Query/Results in Text (Ctrl+T) — результат в виде текста, Results in Grid (Ctrl+D) — в виде таблицы (по умолчанию), Results to File (Ctrl+Shift+F) — cохранение результата в виде файла в собственном формате программы *.rpt.
Таблица Customers состоит из следующих полей (рис. 4.7):
Рис. 4.7. Содержание таблицы Customers
Для извлечения не всей таблицы, а столбцов СustomerID и Address, напишем запрос:
select CustomerID, Address from Customers;
Результатом будет следующее (рис. 4.8):
Рис. 4.8. Извлечение столбцов CustomerID и Address
Если мы сделаем ошибку и укажем поле, которого нет в таблице Customers, например AddressID, в окне результатов на вкладке Messages появится соответствующее предупреждение:
Server: Msg 207, Level 16, State 1, Line 3
Invalid column name 'AddressID'.
Для вывода определенного количества записей используем запрос (рис. 4.9):
select top 5 CustomerID from Customers;

Рис. 4.9. Извлечение нескольких записей
Извлекаются первые пять записей поля CustomerID, расположенные в самой таблице Customers в алфавитном порядке, — этот запрос не производит сортировки!
Вводя оператор percent, получаем указанный процент записей от общего числа:
select top 5 percent CustomerID from Customers;
В данном случае результат будет в точности таким же, как и при использовании запроса без оператора percent. В чем же дело? Общее число записей поля CustomerID таблицы Customers — 91 (В этом нетрудно убедиться: введя запрос select * from Customers;
и переключившись на вкладку , увидим сообщение: (91 row(s) affected).) Простой подсчет показывает, что пять процентов от 91 равняется 4,55; Query Analyzer округляет это число до пяти и возвращает результат.
Для вывода записей, отвечающих заданному условию, используем оператор where:
select * from Products where UnitPrice > 100;
Этот запрос возвращает все записи из таблицы Products, в которых Столбец (поле) UnitPrice имеет значение, большее 100 (рис. 4.10):
Рис. 4.10. Отбор записей со всеми полями по заданному значению
Можно группировать операторы так:
select ProductName,UnitPrice from Products where UnitPrice > 100;
Здесь извлекаются поля ProductName и UnitPrice из таблицы Products, где поле UnitPrice > 100 (рис. 4.11):
Рис. 4.11. Отбор записей с несколькими полями по заданному значению
Оператор where поддерживает работу со знаками <, >, >=, <=.
Точную выборку осуществляет оператор in, в следующем примере извлекаются лишь те записи, в которых значения поля UnitPrice в точности равно либо 10, либо 15, либо 23 (рис. 4.12):
select ProductName,UnitPrice from Products where UnitPrice in (10,15,23);
Рис. 4.12. Отбор записей по точному совпадению значений поля UnitPrice
Выборка для значений, лежащих в указанном интервале, осуществляется оператором between первое _значение and второе_ значение (рис. 4.13):
select ProductName,UnitPrice |
from Products where UnitPrice between 10 and 13; |
Рис. 4.13. Отбор записей по значениям в указанном интервале

Агрегатные функции
При статистическом анализе баз данных необходимо получать такую информацию, как общее количество записей, наибольшее и наименьшее значение заданного поля записи, усредненное значение поля. Это делается с помощью запросов, содержащих так называемые агрегатные функции. Агрегатные функции производят одиночное значение для всей группы таблицы. Имеется список этих функций:
count извлекает количество записей данного поля;
sum извлекает арифметическую сумму всех выбранных значений данного поля;
avg извлекает арифметическое среднее (усреднение) всех выбранных значений данного поля;
max извлекает наибольшее из всех выбранных значений данного поля;
min извлекает наименьшее из всех выбранных значений данного поля.
Для определения общего числа записей в таблице Products используем следующий запрос:
select count (*) from Products;
результатом которого будет (рис. 4.14):
Рис. 4.14. Результат запроса с функцией count
Обратите внимание — на вкладке Messages возникает сообщение, что только одна запись извлечена:
(1 row(s) affected)
Это означает, что агрегатные функции возвращают всего одну запись называемую скалярным значением, в отличие от других запросов, возвращающих наборы записей.
Для определения количества записей поля ProductName таблицы Products используем следующий запрос:
select count (ProductName) from Products;
Таблица Products имеет все заполненные значения полей, поэтому результат этого запроса будет совпадать с результатом извлечением всех записей.
Как быть со значениями полей, которые были незаполненными? Обращение к таким полям осуществляет оператор null. Величина null не означает, что в поле стоит число 0 (нуль) или пустая текстовая строка — " ". Как возникают значения полей null? Существует два способа образования таких значений:
Microsoft SQL Server 2000 автоматически подставляет значение null, если в значение поля не было введено никаких значений и если тип данных для этого поля не препятствует присвоению значения null (если поле не является обязательным для заполнения);
если пользователь явным образом вводит значение null (подробнее о создании таблиц см. далее).
Вы можете самостоятельно попробовать определить, есть ли в какой-либо таблице базы данных Northwind поля, имеющие значения:
select *( или название столбца(ов)) from название_таблицы where название столбца is null;
Для обратной задачи используем запрос типа
select *( или название столбца(ов)) from название_таблицы where название столбца is not null;
Оператор count учитывает записи со значением поля null.
Синтаксис использования других операторов одинаков — следующие запросы извлекают сумму, арифметическое среднее, наибольшее и наименьшее значения поля UnitPrice таблицы Products:
select sum(UnitPrice) from Products; select avg(UnitPrice) from Products; select max(UnitPrice) from Products; select min(UnitPrice) from Products;
Выполните самостоятельно эти запросы и просмотрите результаты.
Типы данных
Для оперирования данными SQL, подобно языкам программирования, использует типы данных. Рассмотрим некоторые из этих типов.
Наиболее употребительными типами данных для хранения чисел являются integer (целое число) и decimal (десятичное число) (которые можно сокращать как int и dec соответственно). Разумеется, что тип "целое число" можно представить как десятичное число, которое не содержит никаких цифр справа от десятичной точки.
Тип для текста — char (или символ), который относится к строке текста. Поле типа char имеет заданную длину, определяемую
максимальным числом символов, которые могут быть введены в это поле. Больше всего реализаций также имеют нестандартный тип, называемый varchar (переменное число символов), который является текстовой строкой, способной принимать любую длину
до определенного реализацией максимума (обычно 254 символа). Значения character и varchar включаются в одиночные кавычки как "текст". Различие между char и varchar в том, что char должен резервировать достаточное количество памяти для максимальной длины строки, а varchar распределяет память так, как это необходимо.
Не все типы значений, которые могут занимать поля таблицы, — логически одинаковые. Наиболее очевидное различие — между числами и текстом. Вы не можете помещать числа в алфавитном порядке или вычитать одно имя из другого. Так как системы с