
- •Содержание
- •Введение
- •1Лабораторная работа № 1 Создание концептуальной модели предметной области
- •1.5Критерии результативности выполнения лабораторной работы
- •Контрольные вопросы
- •2Лабораторная работа № 2 Создание и заполнение реляционной базы данных с помощью языка sql
- •2.1Цель лабораторной работы
- •2.2Задачи лабораторной работы
- •2.3Задание
- •2.4Методика выполнения задания
- •Этап 1. Создание структуры реляционной базы данных и ее модификация
- •Этап 2. Выполнение операций вставки, обновления и удаления данных
- •Этап 3. Выполнение операций выборки данных из одной таблицы
- •2.5Критерии результативности выполнения лабораторной работы
- •Контрольные вопросы
- •3.4Методика выполнения задания
- •Этап 1. Сортировка и встроенные функции
- •Этап 2. Вложенные запросы и операция соединения
- •Этап 3. Создание и обновление представлений
- •3.5Критерии результативности выполнения лабораторной работы
- •Контрольные вопросы
- •4Лабораторная работа № 4 Разработка триггеров и хранимых процедур
- •4.5Курсоры
- •4.6Хранимые процедуры
- •4.7Триггеры
- •4.8Методика выполнения задания
- •4.9Требования к оформлению и содержанию отчета
- •4.10 Критерии результативности выполнения лабораторной работы
- •Контрольные вопросы
- •Список литературы
- •Приложение 1 Варианты заданий для лабораторной работы № 1
- •1. Страховая компания
- •2. Гостиница
- •3. Ломбард
- •4. Реализация готовой продукции
- •5. Ведение заказов
- •6. Бюро по трудоустройству
- •7. Нотариальная контора
- •8. Химчистка
- •9. Курсы повышения квалификации
- •10. Сдача в аренду торговых площадей
- •11. Распределение учебной нагрузки
- •12. Распределение дополнительных обязанностей
- •13. Техническое обслуживание станков
- •14. Туристическая фирма
- •15. Грузовые перевозки
- •Приложение 2 Построение концептуальной модели предметной области в пакете AllFusion eRwin Data Modeler Введение
- •5Описание интерфейса
- •6Создание логической модели данных
- •6.1Сущности и атрибуты
- •6.2Связи
- •6.3Ключи
- •1. Табельный номер,
- •7Создание физической модели данных
- •7.1Выбор сервера
- •7.2Таблицы и колонки
- •Приложение 3. Примеры кода на языке sql
- •Операторы ddl (Data Definition Language)
- •Определение первичных и альтернативных ключей с помощью оператора alter
- •Выборка данных – select
- •Внешние соединения
- •Представления
Контрольные вопросы
Предположим, что создана таблица persons с колонками id, name, age. Какой запрос найдет средний возраст всех людей с возрастом не менее 18-ти лет?
select avg(age) from persons having age >= 18,
Это может быть сделано только с использованием подзапросов,
select avg(age) from persons where age >= 18,
select avg(age) from persons where age >= 18 group by name,
select avg(age) from persons having age >= 18 group by name?
Верно ли составлен следующий запрос:
SELECT EMP_NAME, SUM(SAL) FROM EMPLOYEE?
Какое ключевое слово используется для фильтрации результата GROUP BY запроса?
WHERE,
HAVING,
И WHERE, и HAVING,
ни одно из перечисленных?
Для чего обычно используются представления в базе данных?
4Лабораторная работа № 4 Разработка триггеров и хранимых процедур
Триггер (trigger) – это специальная программа, назначаемая таблице или представлению. Триггер вызывается СУБД, когда пользователь запрашивает вставку, обновление или удаление строки из таблицы или представления, которому принадлежит данный триггер. Microsoft SQL Server поддерживает только замещающие и завершающие триггеры. Предваряющие триггеры этой СУБД не поддерживаются. Таблица может иметь один или несколько завершающих триггеров вставки, обновления и удаления; завершающие триггеры не могут назначаться представлениям. Представление или таблица может иметь не более одного замещающего триггера на каждое из возможных действий – вставку, обновление или удаление.
Хранимая процедура (stored procedure) – это программа, которая выполняет некоторые действия с информацией в базе данных и при этом сама хранится в базе данных. Хранимые процедуры могут принимать входные параметры и возвращать результаты. В отличие от триггеров, которые принадлежат определенной таблице или представлению, хранимые процедуры принадлежат базе данных в целом.
В Oracle хранимые процедуры можно писать на языках PL/SQL и Java. В SQL Server хранимые процедуры пишутся на языке T-SQL.
4.1Цель лабораторной работы
Целью работы является получение практических навыков разработки триггеров и хранимых процедур.
4.2Задачи лабораторной работы
Задачами лабораторной работы являются изучение теоретического материала, необходимого для написания триггеров и хранимых процедур, разработка и отладка набора хранимых процедур с параметрами и без параметров, разработка и отладка триггеров вставки и удаления данных.
4.3Задание
Лабораторная работа выполняется для предметной области, описанной ниже. Прочитайте ее описание и изучите код триггеров и хранимых процедур.
После этого Вам предстоит написать собственные триггеры и хранимые процедуры, список которых представлен далее.
На выполнение лабораторной работы отводится 8 часов.
4.4Описание предметной области – галерея View Ridge
View Ridge – небольшая художественная галерея, которая продает современные произведения европейского и североамериканского искусства, включая литографии, оригинальную живопись и фотографии. Все литографии и фотографии подписаны и пронумерованы, и цена большей части произведений находится в пределах от $5000 до $50 000. View Ridge занимается продажей уже в течение 30 лет. У галереи есть бессменный владелец, три продавца и два рабочих, которые изготавливают рамы, развешивают работы в галерее и готовят их к отправке клиенту. Галерея View Ridge проводит выставки и другие мероприятия для привлечения клиентов. Произведения искусства выставляются также в офисах местных компаний, ресторанах и других общественных местах. Все продаваемые произведения являются собственностью View Ridge; комиссионной торговлей галерея не занимается.
4.4.1 Требования к приложению. Прежде всего, владелец и продавцы желают вести учет личных данных клиентов – их имен, адресов, номеров телефонов и адресов электронной почты.
Кроме того, они хотят знать, творчеством каких художников интересуется тот или иной клиент. Эта информация позволяет продавцам определять, кого следует извещать о поступлении новой работы, а также организовывать персональное общение с клиентами в устной и письменной форме.
Когда галерея покупает произведение, сведения о нем, его авторе, дате и стоимости приобретения записываются в базу данных. В отдельных случаях галерея может выкупить произведение у клиента и вновь выставить его на продажу, так что одно и то же произведение может появляться в галерее неоднократно. При повторном приобретении информация о работе и ее авторе не вводится заново: записывается только дата и стоимость последнего приобретения. Когда работа продается, записываются дата совершения сделки, уплаченная сумма и сведения о покупателе.
Данные о предыдущих продажах необходимы продавцам для того, чтобы они могли уделять больше времени наиболее активным покупателям. Иногда эти записи используются для определения местонахождения ранее проданных произведений.
Для маркетинговых целей требуется, чтобы приложение базы данных выдавало список всех произведений, которые когда-либо появлялись в галерее, и их авторов. Владелец хотел бы также иметь возможность определять, насколько быстро продаются произведения каждого из художников и какова прибыль от их продажи. Наконец, приложение должно отображать список работ, имеющихся в наличии, на веб-странице, к которой потенциальные клиенты могли бы обращаться через Интернет.
Таким образом, перечень требований к приложению для галереи VIEW RIDGE имеет вид:
Вести учет покупателей и их художественных интересов.
Отслеживать приобретения, которые делает галерея.
Отслеживать покупки клиентов.
Вести список художников и произведений, когда-либо появлявшихся в галерее.
Генерировать отчет о том, насколько быстро и с какой прибылью продаются произведения конкретного художника.
Отображать на веб-странице список произведений, выставленных на продажу.
4.4.2 Модель данных. На рис. 4.1 показана модель данных для галереи View Ridge. В ней есть две сильные сущности — CUSTOMER (клиент) и ARTIST (художник). Кроме того, имеется сущность WORK (произведение), идентификационно-зависимая от сущности ARTIST, и сущность TRANSACTION (транзакция), идентификационно-зависимая от сущности WORK. Между сущностями CUSTOMER и WORK имеется неидентифицирующая связь принадлежности.
Сведения о художнике могут присутствовать в базе данных, даже если ни одна из его работ не появлялась в галерее. Это сделано для того, чтобы можно было регистрировать интерес клиентов к художникам, чьи работы галерея может приобрести в будущем. Таким образом, с художником может быть связано любое количество произведений, в том числе ноль.
Идентификатором сущности WORK является группа (Title, Copy) (название, номер копии), поскольку в случае литографий и фотографий произведение может существовать в нескольких экземплярах. Кроме того, в требованиях к приложению указано, что одно и то же произведение может неоднократно появляться в галерее, поэтому с каждым произведением потенциально может быть связано много транзакций. Каждый раз, когда произведение появляется в галерее, необходимо записывать дату и стоимость приобретения. Таким образом, каждой работе должна соответствовать, по меньшей мере, одна транзакция.
Клиент может приобрести множество работ; этот факт обозначен связью вида 1:N между сущностями CUSTOMER и TRANSACTION. Данная связь является необязательной в обоих направлениях. Наконец, между сущностями CUSTOMER и ARTIST существует связь вида N:M. Это реальная связь «многие ко многим».
Рис. 4.1. Реляционная схема с использованием данных в качестве ключей
На рис. 4.1 показана реляционная схема для модели данных. В этом варианте в качестве ключей используются данные, и, как можно видеть, с каждым первичным ключом, за исключением ARTIST.Name, связаны какие-нибудь проблемы. Ключи таблиц WORK и TRANSACTION чересчур велики, а ключ таблицы CUSTOMER и вовсе сомнителен: далеко не у всех покупателей имеется адрес электронной почты. В связи с этим напрашивается очевидное решение — ввести суррогатные ключи.
Рис. 4.2. Реляционная схема с суррогатными ключами
Вместо двух идентификационно-зависимых связей появились две неидентифицирующие связи. Теперь, когда сущность ARTIST имеет суррогатный ключ, исчезла потребность в композитных идентификационно-зависимых ключах для сущностей WORK и TRANSACTION.
Атрибут ARTIST.Name определен как альтернативный ключ. Тем самым гарантируется, что в базе данных не будет нескольких записей об одном и том же художнике. Аналогичным образом в качестве альтернативного ключа определена комбинация (Title, Copy), чтобы нельзя было одну и ту же работу записать в базу данных несколько раз.
Все ключи представлены как суррогатные в формате IDENTITY (n, т), где п — начальное значение суррогатного ключа, a m – приращение. Все ключи имеют приращение, равное 1, но разные начальные значения.
Атрибут TRANSACTION.CustomerID может иметь пустые значения; это позволяет создать строку в таблице TRANSACTION до того, как произведение приобретет какой-нибудь клиент. Все прочие внешние ключи являются обязательными.
4.4.3 Процедуры обеспечения ссылочной целостности со стороны родительских таблиц. Удаление строк в таблицах CUSTOMER и ARTIST вызывает каскадное удаление в таблице CUSTOMER_ARTIST_INT. Это имеет смысл, поскольку, когда сведения о клиенте или художнике удаляются из базы данных, нет нужды сохранять информацию о предпочтениях данного клиента или интересе к данному художнику. Помимо этого, каскадное удаление больше нигде не применяется.
Если с клиентом связана хотя бы одна транзакция, этот клиент не может быть удален из базы данных. Аналогично, если с художником связана хотя бы одна картина, удалить его будет нельзя. Наконец, записи о работах, по которым имели место какие-либо транзакции, удалению также не подлежат.
Последнее обстоятельство ставит нас перед проблемой. Когда в базу данных добавляется новое произведение, для него должна быть создана строка в таблице TRANSACTION, в которой будут указаны дата и стоимость приобретения. Поэтому с каждой из работ должна быть связана, по крайней мере, одна транзакция. Однако последнее правило, касающееся удаления, гласит, что нельзя удалить работу, с которой связана хотя бы одна транзакция. Таким образом, работу невозможно удалить из базы данных, даже если она никогда не была продана.
Возможно, галерея вообще не желает удалять сведения о работах, однажды добавленных в базу данных. Если нет, то можно ввести следующее правило: если работа появлялась в галерее только один раз, и при этом не была продана (столбец CustomerID в соответствующей строке таблицы TRANSACTION пуст), то работу можно удалить из базы данных. В нашем примере мы будем подразумевать последний случай. Для обработки удаления нам потребуется создать триггер.
Во всех связях вида «родитель-потомок» обновление родительской таблицы вызывает каскадное обновление дочерней. В действительности это правило не нужно, поскольку значения суррогатных ключей никогда не меняются. Наконец, вставка с родительской стороны обрабатывается согласно стандартным правилам обеспечения ссылочной целостности. Например, значение атрибута WORK.ArtistID должно существовать среди значений атрибута ARTIST.ArtistID. О соблюдении всех этих ограничений позаботится СУБД, от нас же требуется лишь указать их на схеме.
4.4.4 Процедуры обеспечения ссылочной целостности со стороны дочерних таблиц. Обновление со стороны дочерних таблиц ограничено. Ни при каких условиях не должно возникать необходимости в изменении значения внешнего ключа в таблицах CUSTOMER_ARTIST_INT, WORK и TRANSACTION (столбец WorkID), следовательно, в данном случае слово «ограничено» обозначает, что обновление просто не допускается. Что касается столбца TRANSACTION.CustomerID, то его значение изменяется при первой продаже работы. После этого, однако, значение CustomerID меняться не должно. Таким образом, если столбец CustomerID пуст, его обновление возможно; в противном случае обновление не допускается. Это правило также необходимо реализовать с помощью триггера.
При вставке строк в таблицы WORK и TRANSACTION их внешним ключам присваиваются начальные значения (процедура SD), а именно значения ключей соответствующих строк в таблицах ARTIST и WORK. Внешний ключ CustomerID таблицы TRANSACTION при вставке определяется как пустой, и пустым он останется до тех пор, пока кто-нибудь не купит данное произведение.
Удаление строк в таблицах WORK и TRANSACTION объявлено как ограниченное, но по разным причинам. Если столбец TRANSACTION.CustomerID не является пустым, строка не может быть удалена. Если он пуст, строку можно удалить только при условии, что данная транзакция является единственной для некоторого произведения, и данное произведение само будет удалено из базы. Как было указано выше, эта пара ситуаций должна обрабатываться с помощью триггеров.
Наконец, произведение можно удалить, если с ним связана одна-единственная транзакция с пустым столбцом CustomerID. Строки таблицы CUSTOMER_ARTIST_INT могут быть удалены как в процессе каскадного удаления, так и непосредственно приложением, когда клиент решает, что его более не интересует тот или иной художник.
4.4.5 Создание и заполнение таблиц. SQL-процедура, создающая таблицы базы данных галереи View Ridge, представлена в листинге 1. Она состоит из пяти операторов CREATE TABLE – по одному на каждую из таблиц. В листинге используется стиль записи, при котором разработчик может давать имена всем ограничениям. Столбец TRANSACTION.CustomerID определен как необязательный; все остальные первичные ключи являются обязательными.
Листинг 1. Создание таблиц для базы данных галереи View Ridge
CREATE TABLE CUSTOMER(
CustomerID int NOT NULL IDENTITY (1000, 1),
Name char(25) NOT NULL,
Street char(30) NULL,
City char(35) NULL,
State char(2) NULL,
ZipPostalCode char(6) NULL,
Country char(50) NULL,
AreaCode char(3) NULL,
PhoneNumber char(8) NULL,
Email char(100) NULL,
CONSTRAINT CustomerPK PRIMARY KEY (CustomerID)
);
CREATE TABLE ARTIST(
ArtistID int NOT NULL IDENTITY (1, 1),
ArtistName char(25) NOT NULL,
Nationality char(30) NULL,
BirthDate numeric(4) NULL,
DeceasedDate numeric(4) NULL,
CONSTRAINT ArtistPK PRIMARY KEY (ArtistID),
CONSTRAINT ArtistAKl UNIQUE (ArtistName),
CONSTRAINT NationalityValues CHECK (Nationality IN ('Canadian', 'English', 'French', 'German', 'Mexican', 'Russian', 'Spanish', 'US')),
CONSTRAINT BirthValuesCheck CHECK (BirthDate < DeceasedDate),
CONSTRAINT ValidBirthYear CHECK (BirthDate LIKE '[1-2][0-9][0-9][0-9]'),
CONSTRAINT ValidDeathYear CHECK (DeceasedDate LIKE '[1-2][0-9][0-9][0-9]')
);
CREATE TABLE CUSTOMER_ARTIST_INT(
ArtistID int NOT NULL,
CustomerID int NOT NULL,
CONSTRAINT CustomerArtistPK PRIMARY KEY (ArtistID, CustomerID),
CONSTRAINT Customer_Artist_Int_ArtistFK
FOREIGN KEY (ArtistID) REFERENCES ARTIST (ArtistID)
ON UPDATE CASCADE
ON DELETE CASCADE,
CONSTRAINT Customer_Artist_Int_CustomerFK
FOREIGN KEY (CustomerID) REFERENCES CUSTOMER (CustomerID)
ON UPDATE CASCADE
ON DELETE CASCADE
);
CREATE TABLE WORK(
WorkID int NOT NULL IDENTITY (1, 1),
Title char(25) NOT NULL,
Copy char(8) NOT NULL,
Description varchar(100) NULL,
ArtistID int NOT NULL,
CONSTRAINT WorkPK PRIMARY KEY (WorkID),
CONSTRAINT WorkAKl UNIQUE (Title, Copy),
CONSTRAINT ArtistFK FOREIGN KEY (ArtistID) REFERENCES ARTIST (ArtistID)
);
CREATE TABLE TRANS (
TransactionID int NOT NULL IDENTITY (100, 10),
DateAcquired datetime NOT NULL,
AcquisitionPrice numeric(8, 2) NULL,
PurchaseDate datetime NULL,
SalesPrice numeric(8, 2) NULL,
CustomerID int NULL,
AskingPrice numeric(8, 2) NULL,
WorkID int NOT NULL,
CONSTRAINT TransactionPK PRIMARY KEY (TransactionID),
CONSTRAINT SalesPriceRange
CHECK ((SalesPrice > 1000) AND (SalesPrice <= 200000)),
CONSTRAINT ValidTransDate CHECK (DateAcquired <= PurchaseDate),
CONSTRAINT TransactionWorkFK
FOREIGN KEY (WorkID) REFERENCES WORK (WorkID),
CONSTRAINT TransactionCustomerFK
FOREIGN KEY (CustomerID) REFERENCES CUSTOMER (CustomerID)
);
Столбцы BirthDate (дата рождения) и DeceasedDate (дата смерти) определены как четырехзначные числа, обозначающие год. Сотрудникам галереи не важны месяц и день рождения и смерти, им достаточно знать лишь год.
Наиболее распространены два типа ограничений: диапазоны и перечисления. Пример ограничения первого типа можно видеть в таблице TRANS, где столбец SalesPrice (продажная цена) должен иметь значение, превышающее 1000, но меньшее или равное 200000.
Ограничение второго типа имеет место в определении таблицы ARTIST. Здесь множество значений столбца Nationality (национальность) ограничивается только теми значениями, которые перечислены в скобках. Это ограничение отражает политику галереи работать только с произведениями европейских и североамериканских художников.
Есть также ограничения, сравнивающие между собой значения двух столбцов. Например, ограничение BirthValuesCheck (проверка даты рождения) в таблице WORK предписывает, что значение столбца BirthDate (дата рождения) должно быть меньше, чем DeceasedDate (дата смерти). Похожее ограничение сформулировано в определении таблицы TRANS.
Еще один тип ограничений – ограничения формата. В определении таблицы ARTIST на столбцы BirthDate и DeceasedDate наложено ограничение, согласно которому они должны состоять из четырех десятичных цифр, причем первой цифрой должна быть 1 или 2. Таким образом, значения вроде 799 или 3100 являются для этих столбцов недопустимыми.
Согласно стандарту SQL-92, ограничения CHECK не могут включать системную дату. Для таких столбцов, как PurchaseDate (дата приобретения), весьма полезным было бы ограничение, в соответствии с которым значение столбца должно быть меньше или равно текущей дате. Это ограничение можно реализовать с помощью триггера.
Существует еще один интересный тип ограничений CHECK (не показан в листинге 1) – ограничения, содержащие в себе вложенный запрос. Предположим, например, что таблица STATECODE (код штата) имеет столбец ValidStateAbbreviation (допустимое сокращение штата), содержащий все допустимые сокращения названий штатов. Тогда в оператор CREATE TABLE для таблицы CUSTOMER можно было бы добавить следующее ограничение:
CONSTRAINT ValidStateCheck CHECK (State IN
(SELECT ValidStateAbbreviation FROM STATECODE WHERE ValidStateAbbreviation = State))
Такое ограничение, однако, может быть реализовано не во всех СУБД.
Листинг 2. Заполнение таблиц для базы данных галереи View Ridge
--клиенты:
INSERT INTO CUSTOMER (Name, Street, City, State, ZipPostalCode, Country, AreaCode,PhoneNumber,Email)
VALUES
('Brown John', 'California_STR 4', 'Los-Angeles','CA','290040','United States of America','236','44345679','usaforever@mail.by');
INSERT INTO CUSTOMER (Name,Street,City,State,ZipPostalCode,Country,AreaCode,PhoneNumber,Email)
VALUES
('Francua Lower', 'Main_STR 15', 'Paris','EU','888569','France','009','441345','bestfrance@bk.com');
INSERT INTO CUSTOMER (Name,Street,City,State,ZipPostalCode,Country,AreaCode,PhoneNumber,Email)
VALUES
('Aleksandr Stolz', 'Branderburg_STR', 'Koln','DE','107843','Germany','874','314209','lovedeutchland@gmail.de');
--художники:
INSERT INTO ARTIST (ArtistName,Nationality,BirthDate,DeceasedDate) VALUES
('Ferdinand Delacroix', 'French', '1798','1863');
INSERT INTO ARTIST (ArtistName,Nationality,BirthDate,DeceasedDate) VALUES
('Albrecht Durer', 'German', '1471','1528');
INSERT INTO ARTIST (ArtistName,Nationality,BirthDate,DeceasedDate) VALUES
('John Constebl', 'English', '1776','1837');
--работы:
INSERT INTO WORK (Title,Copy,Description,ArtistID) VALUES
('Сирота','00000001','Description','1');
INSERT INTO WORK (Title,Copy,Description,ArtistID) VALUES
('Сирота ','00000002','Description','1');
INSERT INTO WORK (Title,Copy,Description,ArtistID) VALUES
('ПОРТРЕТ ОТЦА','00000001','Description','1');
INSERT INTO WORK (Title,Copy,Description,ArtistID) VALUES
('Свобода на баррикадах','00000001','Description','2');
INSERT INTO WORK (Title,Copy,Description,ArtistID) VALUES
('Метель','00000001','Description','3');
INSERT INTO WORK (Title,Copy,Description,ArtistID) VALUES
('Скачущая лошадь','00000001','Description','3');
--5 транзакций:
INSERT INTO TRANS (DateAcquired, AcquisitionPrice, PurchaseDate, SalesPrice, CustomerID, AskingPrice, WorkID)
VALUES ('2010/07/04', 1000, '2010/07/08', 1400, 1000, 1500, 4);
INSERT INTO TRANS (DateAcquired, AcquisitionPrice, AskingPrice, WorkID) VALUES ('2010/07/08', 10000, 12000, 5);
INSERT INTO TRANS (DateAcquired, AcquisitionPrice, AskingPrice,WorkID)
VALUES ('2010/07/04',30000,50000,6);
INSERT INTO TRANS (DateAcquired, AcquisitionPrice, PurchaseDate, SalesPrice, CustomerID, AskingPrice,WorkID)
VALUES ('2010/08/04',50000,'2010/09/04',77000,1002,100000,3);
INSERT INTO TRANS(DateAcquired, AcquisitionPrice, PurchaseDate, SalesPrice, CustomerID, AskingPrice, WorkID)
VALUES ('2010/08/06',44000,'2010/10/06',50000,1002,60000,2);
--заполнение таблиц
INSERT INTO CUSTOMER_ARTIST_INT VALUES (1, 1000);
INSERT INTO CUSTOMER_ARTIST_INT VALUES (1, 1001);
INSERT INTO CUSTOMER_ARTIST_INT VALUES (1, 1002);
INSERT INTO CUSTOMER_ARTIST_INT VALUES (2, 1000);
INSERT INTO CUSTOMER_ARTIST_INT VALUES (2, 1001);
INSERT INTO CUSTOMER_ARTIST_INT VALUES (2, 1002);
INSERT INTO CUSTOMER_ARTIST_INT VALUES (3, 1000);
INSERT INTO CUSTOMER_ARTIST_INT VALUES (3, 1001);
INSERT INTO CUSTOMER_ARTIST_INT VALUES (3, 1002);