 |  | |  | |
TMySQL - компонент для доступа к MySQL | Полный текст материала
Другие публикации автора: Дмитрий Ларионов
Цитата или краткий комментарий: «... TMySQL - компонент для доступа к MySQL ...» |
Важно:- Страница предназначена для обсуждения материала, его содержания, полезности, соответствия действительности и так далее. Смысл не в разборке, а в приближении к истине :о) и пользе для всех.
- Любые другие сообщения или вопросы, а так же личные эмоции в адрес авторов и полемика, не относящаяся к теме обсуждаемого материала, будут удаляться без предупреждения авторов, дабы не мешать жителям нормально общаться.
- При голосовании учитывайте уровень, на который расчитан материал. "Интересность и полезность" имеет смысл оценивать относительно того, кому именно предназначался материал.
- Размер одного сообщений не должен превышать 5К. Если Вам нужно сказать больше, сделайте это за два раза. Или, что в данной ситуации правильнее, напишите свою статью.
Всегда легче осудить сделанное, нежели сделать самому. Поэтому, пожалуйста, соблюдайте правила Королевства и уважайте друг друга.
Добавить свое мнение.
| | Содержит полезные и(или) интересные сведения | [1] | 29 | 100% | | | | Ничего особенно нового и интересного | [2] | 0 | 0% | | | | Написано неверно (обязательно укажите почему) | [3] | 0 | 0% | | Всего проголосовали: 29 | | | Все понятно, материал читается легко | [1] | 27 | 100% | | | | Есть неясности в изложении | [2] | 0 | 0% | | | | Непонятно написано, трудно читается | [3] | 0 | 0% | | Всего проголосовали: 27 |
[mySQL]
Отслеживать это обсуждение 
Всего сообщений: 16517-08-2013 08:12На localhost все ок а по сети не могу приконектиться. Что это может быть? Фаервол отключен. Антивируса нет
может кому пригодится - в настройках сервера mysql нужно убрать параметр —skip-networking либо закоментировать |
|
04-08-2011 14:38Дмитрий, я давно пользуюсь Вашим классом, очень им доволен. Спасибо Вам за него!
Решил вынести код в отдельный design-time пакет. Но столкнулся с проблемой.
Для примера:
Имеем модуль компонента-наследника TEdit:
unit MyEdit;
interface
uses
StdCtrls,
Classes,
SysUtils;
type
TMyEdit=class(TEdit)
private
FFlag: boolean;
published
property Flag:boolean Read FFlag Write FFlag;
end;
procedure Register;
implementation
uses MySQLClasses;
procedure Register;
begin
RegisterComponents('My',[TMyEdit]);
end;
end.
Помещаем этот модуль в отдельный пакет.
В этот же пакет в секцию Contains помещаем MySQL.pas и MySQLClasses.pas.
Компилируем - Всё Ок.
Нажимаем Install - падает ошибка "Can't load package. Неверная попытка доступа к памяти".
Убираем MySQLClasses, оставляя MySQL - всё Ок.
Где косяк? |
|
31-07-2011 23:12
18-07-2011 06:58Сначала испугался "красной строчки" - шестая делфя отказалась распознать тип TFormatSettings, однако, чуток потыкавшись в гугле
http://delphi.about.com/library/rtl/blrtlTFormatSettings.htm
нашел его определение и всё заработало.
Добрую неделю искал в гугле ответ на гласный, разбавленный ненормативной лексикой вопрос "как" и это первая ссылка, на которой нашелся актуальный материал. В общем, спасибо.
п.с. да, я знаю, что я некропостерСообщение не подписано |
|
06-04-2011 10:18сообщение от автора материала Скажите, а возможно в принципе изменить api интерфейс для работы через http-туннель?
Имеется ввиду сама mysql не имеет внешнего выхода, а на сервере лежит скрипт который общается с mysql, а библиотека бы общалась бы с этим скриптом? К сожалению такого функционала не писал и не интересовался наличием сторонних решений по причине ненадобности.
Во-первых наверняка решения должны быть, поэтому традиционный посыл в гугл :) "mysql http туннель" наверняка даст результаты.
Во-вторых собственный "туннель" написать дело ну ни такое уж и сложное, дня наверно хватит. Скорей всего тебе достаточно функций принять/послать данные. Indy компоненты; банальные post запросы на запрос/отправку данных; авторизация через куки; подумать в каком виде удобнее работать с данными (json, xml, cvs, ...). Практически и всё. |
|
06-04-2011 07:22Здравствуйте.
Очень полезные компоненты. Автору мегареспект.
Скажите, а возможно в принципе изменить api интерфейс для работы через http-туннель? На сколько я знаю, хостеры часто дают доступ только так или по ssh |
|
07-02-2011 04:47сообщение от автора материала а это так важно?
просто подсказать нельзя?
Ну ё-моё, чуть что хватаются за нож и готовы биться с невидимым врагом до последнего.
Я лишь спросил: "как в сообщении от такого-то числа сделать не получается?". Не буду же я его и 5-10 последующих переписывать.
Посмотрите, пожалуйста, его и последующие. |
|
06-02-2011 00:33непонял
у меня дата сообщения 03-02-2011 11:34
а это так важно?
просто подсказать нельзя? |
|
04-02-2011 13:22сообщение от автора материала никак не могу разобраться как передавать данные в блоб поле!
Так "30-01-2008 01:36" не получается?
|
|
03-02-2011 11:34Здравствуйте!
никак не могу разобраться как передавать данные в блоб поле!
есть переменная с изображением:
jpg :TJpegImage;
запрос должен быть такого типа:
MySQL.ExecSQL('INSERT INTO basa (pole1,pole2) VALUES ('test', КАРТИНКА)')
я вот не пойму как сделать чтобы вместо КАРТИНКА был jpg
Спасибо!
|
|
14-01-2011 13:15to flai:
Пожалуй, хватит уже, а? Данная тема — обсуждение конкретной статьи. Все остальное — оффтоп. Поиск исполнителя для работы — злостный оффтоп. Есть городская площадь. Есть, в конце концов, СЛС или электронная почта. Только не злоупотребляйте и не будьте слишком навязчивым. |
|
13-01-2011 10:34сообщение от автора материала Я с MySql знаком не по наслышке а вот с Делфи увы второй рас всего сталкиваюсь.
Хм. Ну ты смотри, на мой демо как на икону не полагайся, там моск работал на холостых оборотах. Я туда кода понапихал только чтобы показать как и что можно вызывать...
Можно ли сделать редактирование данных во второй таблице? И именно редактировать данные которые загружаются после выбора категории.
Для редактирования существуют различные grid'ы, можно вызывать дополнительные диалоговые окна с полями ввода. Как в ListView комфортно редактировать я не знаю, там стандартно поле для ввода появляется только в первой колонке.
Как на php сделать знаю, а не делфи нет.
Ну по большому счёту так же. Ты либо по окончании редактирования какой-то строки формируешь sql команду (insert, update, delete) и выполняешь его MySql.ExecSql(), либо, например, с помощью компонент Indy отправляешь на сервер стандартный вебовский POST (ключ=значение&ключ=значение...), а на сервере его скриптами обрабатываешь, незабывая, кстати, блюсти секьюрность (куки, права доступа, и т.д.). |
|
13-01-2011 10:11Кто может данный скрипт переписать под конкретное задание?
О размере вознаграждения договоримся!
Пишите мне на мыло. |
|
13-01-2011 07:45Большое спасибо за помощь!
Я с MySql знаком не по наслышке а вот с Делфи увы второй рас всего сталкиваюсь.
А можно еще один вопрос?
Можно ли сделать редактирование данных во второй таблице? И именно редактировать данные которые загружаются после выбора категории. Как на php сделать знаю, а не делфи нет.
Заранее спасибо! |
|
13-01-2011 02:22сообщение от автора материала Твой вопрос не связан с MySql, поэтому если будут и дальше возникать посторонние проблемы, то лучше направлять их на "круглый стол".
ListItem := lvGroups.Items.Add;
ListItem.Caption := Str;
ListItem.Caption := Str1;
Ну и что должен после этого показывать ListView?
Текст в дополнительные колонки ListView добавляется следующим образом:
ListItem := ListView.Items.Add;
ListItem.Caption := 'aaa';
ListItem.SubItems.Add('bbb');
ListItem.SubItems.Add('ccc');
|
|
12-01-2011 10:51Помогите ночевку! пытаюсь сделать к группе описание, исправил ваш пример.
with TForm2.Create(nil) do
try
if ShowModal = idOk then
begin
Str := Edit1.Text;
Str1 := Edit2.Text;
end else
Exit;
finally
Free;
end;
MySQL.ExecSQL(
' INSERT INTO `groups` (`name`,`desk`)'
+ ' VALUES ('
+ MySQLStr(MySQL, Str) + ','
+ MySQLStr(MySQL, Str1)
+ ' )');
Id := MySQLInsertId(MySQL);
if Id <> 0 then
begin
ListItem := lvGroups.Items.Add;
ListItem.Caption := Str;
ListItem.Caption := Str1;
New(Data);
Data.id := IntToStr(Id);
ListItem.Data := Data;
end;
А сейчас вопрос: Не выводит вторую колонку только после подключения помогите плиз! |
|
26-11-2010 12:17сообщение от автора материала А путём поиска можно мыло обойтись без вот, путем проб и ошибок сделал... - сообщение от "29-01-2008 05:18".
Ещё есть ответы как в обратную сторону. |
|
26-11-2010 07:47вот, путем проб и ошибок сделал код загрузки jpg изображения из blob поля через TMemoryStream, может кому будет полезно.
var imgStr:string;
query_result: IMySQLQuery;
streamImg: TMemoryStream;
JpgImg: TJPEGImage;
...
imgStr := query_result.ValueByName['photo'];
streamImg := TMemoryStream.Create;
try
streamImg.Write(Pointer(imgStr)^, Length(imgStr));
streamImg.Position := 0;
JpgImg:=TJPEGImage.Create;
try
Img1.Picture.Graphic:=NIL;
JpgImg.LoadFromStream(StreamImg);
Img1.Picture.Graphic:=TJPEGImage.Create;
Img1.Picture.Graphic.Assign(jpgImg);
finally
JpgImg.Free;
end;
finally
streamImg.free;
end;
|
|
25-11-2010 02:11 В результате-то что случилось? Ты поправил код как в моём предыдущем сообщении (для версии 5.1), а взял dll 5.0 или ты ничего не правил, а с 5.0 не работает?
У меня несколько MySql серверов. Есть 5.0 и 5.1. Так вот подправил
st_mysql_field = record
name, org_name,
table, org_table,
db,
catalog,
def: PAnsiChar;
length, max_length,
name_length, org_name_length,
table_length, org_table_length,
db_length, catalog_length,
def_length,
flags, decimals,
charsetnr: Cardinal;
_type: enum_field_types;
extension: pointer;
end;
Скопировал dll, не заработало. Потом оказалось что это не та dll-ка была. Скопировал dll от Mysql 5.1 - все отлично работает. |
|
24-11-2010 00:52сообщение от автора материала Сорри. Всё заработало. Оказалось что у меня libmysql.dll была версии 5.0
Я всегда знал, что проблему не надо решать сразу при её возникновении - через сутки она или сама отвалится или изменится :)
На самом деле мне письмо не пришло о новом сообщении в комментариях.
В результате-то что случилось? Ты поправил код как в моём предыдущем сообщении (для версии 5.1), а взял dll 5.0 или ты ничего не правил, а с 5.0 не работает? |
|
23-11-2010 23:47Сорри. Всё заработало. Оказалось что у меня libmysql.dll была версии 5.0 |
|
23-11-2010 07:45Вот еще одна проблема. Использование структуры as в запросе вернет только один столбец, первый. Вот код измененный в демо, при нажатии на группу ничего не выведется
...
'SELECT' + #13#10 +
'id,' + #13#10 +
'pid,' + #13#10 +
'first_name as fn,' + #13#10 +
'last_name as ln,' + #13#10 +
'dr,' + #13#10 +
'phone,' + #13#10 +
'address' + #13#10 +
'FROM' + #13#10 +
'mydb_test.book' + #13#10 +
'WHERE `pid`=' + GroupData.id
);
if query_result = nil then
begin
ShowMySQLError;
Exit;
end;
while query_result.FetchRow do
begin
ListItem := lvBook.Items.Add;
ListItem.Caption := query_result.ValueByName['fn'];
ListItem.SubItems.Add(query_result.ValueByName['ln']);
ListItem.SubItems.Add(query_result.ValueByName['dr']);
ListItem.SubItems.Add(query_result.ValueByName['phone']);
ListItem.SubItems.Add(query_result.ValueByName['address']);
New(BookData);
BookData.id := query_result.ValueByName['id'];
BookData.pid := query_result.ValueByName['pid'];
ListItem.Data := BookData;
end;
...
|
|
03-04-2010 14:43Действительно, все заработало! Спасибо, riff |
|
03-04-2010 07:21сообщение от автора материала Повторюсь, конструкция запроса 'SELECT * FROM' ...' обрабатывается отлично, запрос типа 'SELECT col1,col2.... FROM' возвращает только "col1".
Скачал сейчас libmysql.dll 5.1. Проверил, демо-пример действительно перестал работать.
На самом деле данные все возвращаются нормально, просто описание поля чуть изменилось:
st_mysql_field = record
name, org_name,
table, org_table,
db,
catalog,
def: PAnsiChar;
length, max_length,
name_length, org_name_length,
table_length, org_table_length,
db_length, catalog_length,
def_length,
flags, decimals,
charsetnr: Cardinal;
_type: enum_field_types;
extension: pointer;
end;
возможно есть ещё где-нибудь изменения в заголовках, но пока не сверял. А добавив эту строку, у меня демо заработал. |
|
03-04-2010 06:44Я этот пример привел для нагладности. На самом деле, вместо 'count' может быть любое значение. Повторюсь, конструкция запроса 'SELECT * FROM' ...' обрабатывается отлично, запрос типа 'SELECT col1,col2.... FROM' возвращает только "col1". |
|
03-04-2010 06:17сообщение от автора материала 1. Проверь название поля возвращаемое в запросе, как ни как count-это зарезервированное слово: "query_result.FieldName[1]" (не помню отсчёт полей начинается с нуля или единицы, если с единицы, то FieldName[2]).
2. Пока не проверил, но, на вскидку, исчезнет ошибка, если в запросе поле count заключить в такие ` кавычки? |
|
03-04-2010 05:57Здравствуйте! При использовании прилагаемой к компоненту библиотеки libmysql.dll все работало отлично пока на взял эту dll из MySql 5.1.
При запросе не всех данных таблицы, а части, происходит ошибка:
query_result := MySQL.Query('SELECT name,count FROM `groups`');
if query.FetchRow then
begin
....Caption := query_result.ValueByName['name'];//Caption получено
....Caption := query_result.ValueByName['count'];// Ошибка
..................... |
|
13-03-2010 07:02Заработало!!! Причина в том, что переменную надо было объявлять не как тип класс, как тип интерфейс:
var
MySQLConnect: TMySQL; //не правильно!!!
MySQLConnect: IMySQL; //правильно!!!
|
|
13-03-2010 06:47А я столкнулся с глюком, который скорее всего связан с COM. В отдельном модуле создаю глобальную переменную (чтобы можно было использовать ее во всех модулях):
var
MySQLConnect: TMySQL;
Создаю ее в этом же модуле:
initialization
MySQLConnect := TMySQL.Create;
А потом, когда удаляется компонент, полученный в результате операции Query удаляется и сам MySQLConnect. Я проверил поставив точки останова в деструкторе TMySQLQuery.Destroy;
И, например, код
var
MySQL: IMySQLQuery;
begin
MySQL := MySQLConnect.Query(SQL_SELECT_THEME_NAME);
try
if MySQL = nil then
ErrorDlg;
<<<>>>
finally
MySQL := nil;
MySQLConnect.ExecSQL('SET CHARSET cp1251');//здесь ошибка!!!
end;
выдает ошибку при вызове MySQLConnect.ExecSQL() после того, как MySQL:=nil; Даже если не присваивать nil, в другой процедуре все равно MySQLConnect.ExecSQL() выдаст ошибку с адресацией.
Что делать???
|
|
23-01-2010 07:27сообщение от автора материала Спасибо за положительный отзыв.
Правда пришлось "допилить" переведя с функций, возвращающих значения, на процедуры с Exception's при наличии ошибок.
На слух сложно воспринимать, что именно ты правил. Но вообще я специально не добавлял никаких exceptions, дабы оставаться ближе к оригиналу API. Проще, мне кажется, проверять возвращаемый функциями результат, чем обвешивать их try..except. |
|
23-01-2010 06:32Очень пригодилось.
Большое спасибо автору.
Правда пришлось "допилить" переведя с функций, возвращающих значения, на процедуры с Exception's при наличии ошибок.
Но все равно очень пригодилось.
Иногда (как в моем случае - пакетная перегрузка из DBF в "Мускул") DB компоненты это излишество и существенная потеря производительности. А low level API - то что доктор прописал! |
|
30-10-2009 08:08сообщение от автора материала удаленному серверу нет подключения, и самое интересное то, что провайдерский сервер не даёт соединения э-э-э, в смысле? Т.е. стоит запрет на внешние подключения, но тебе всё равно хочется?
Перепробовал кучу mySQL-компонентов и везде один и тот результат. В таком случае ответ очевиден: можешь ещё кучу перепробовать...
Или доступ разрешён, но не соединяется? |
|
30-10-2009 07:32Столкнулся с такой-же проблемой, когда на локалхосте всё замечательно работает, а к удаленному серверу нет подключения, и самое интересное то, что провайдерский сервер не даёт соединения (пробовал через троих разных провайдеров). Проблема актуальная. Перепробовал кучу mySQL-компонентов и везде один и тот результат. |
|
30-09-2009 07:20сообщение от автора материала дык надо не в файл,в Timage выводить.
или имелось ввиду через временный файл...
Можешь использовать TMemoryStream.
Если не трудно, то приведите пример как тот же test.jpg положить в блоб поле.
Я давно с блоб полями не имел дело, наизусть точно не скажу. На круглом столе таких примеров много. В поиск. |
|
30-09-2009 04:45Ок, нижеприведенный пример работает.
Если не трудно, то приведите пример как тот же test.jpg положить в блоб поле.
Спасибо! |
|
30-09-2009 04:38дык надо не в файл,в Timage выводить.
или имелось ввиду через временный файл... |
|
30-09-2009 03:00сообщение от автора материала var
query: IMySQLQuery;
S: string;
begin
query := MySQL.Query('SELECT * FROM ...');
if query = nil then
begin
Exit;
end;
if query.FetchRow then
begin
s := query.ValueByName['img'];
with TFileStream.Create('f:\test.jpg', fmCreate) do
try
Write(Pointer(s)^, Length(s));
finally
Free;
end;
end;
end; |
|
30-09-2009 01:59не получается работать с блоб полями
вот пример (в блобе лежит картинка jpeg):
var
query_result: IMySQLQuery;
ii: TBlobField;
S: TMemoryStream;
begin
S := TMemoryStream.Create();
ii.value := query_result.ValueByName['img']; // вот тут происходит Access violation...
ii.SaveToStream(s);
try
Img.Picture.Bitmap.LoadFromStream(S);
finally
S.Free;
end; // try
end;
что не так делаю?
Спасибо! |
|
03-09-2009 08:25Да, хэшированными. если длина = 16, то в старом формате; длинней - в новом.
длина что-то в районе 40-50 символов, досчитал до 20, визуально прикинул остаток :)
Локально поставил мускуль 5.0, на удаленных серверах тоже он глубокая мысль :) Дна не увидел.
судя по всему, дно примерно где-то тут
MySQL 5.0 uses an authentication protocol based on a password hashing algorithm that is incompatible with that used by older (pre-4.1) clients.
Потому и сообщаю, что либа у меня от 5-й версии и коннекчусь к 5-ой версии же. При этом никаких дополнительных телодвижений с паролями не произвожу и, судя по размеру хэша, пароль сей нового образца. Размер файла libmysql.dll - 2 068 480 байт, данных о версии, к сожалению, внутри нет.
|
|
03-09-2009 02:56сообщение от автора материала Судя по той абракадабре, которую вывел select user,password from user - пароли хранятся уже хэшированные.
Да, хэшированными. если длина = 16, то в старом формате; длинней - в новом.
Локально поставил мускуль 5.0, на удаленных серверах тоже он глубокая мысль :) Дна не увидел. |
|
03-09-2009 02:48кстати: скачал, запустил демку, локально все красиво а локально у тебя в каком виде пароли? (База mysql/таблица user/колонка password). Или ты локально без паролей?
да нет, с паролями. Судя по той абракадабре, которую вывел select user,password from user - пароли хранятся уже хэшированные. Локально поставил мускуль 5.0, на удаленных серверах тоже он, и туда и туда коннект прошел нормально. |
|
03-09-2009 02:24сообщение от автора материала а разве этот функционал не в libmysql.dll? Я думаю, что версия библиотеки должна совпадать с версией сервера, к которому поключаешься
Я свою libmysql взял из установочного пакета, но она всё равно подключается только к паролю старой версии. Я думал может какой-нибудь флаг при подключении есть или ещё чего. Ни чего не нашёл (хотя не сильно и искал). Будет чуть времени ещё раз поищу.
кстати: скачал, запустил демку, локально все красиво а локально у тебя в каком виде пароли? (База mysql/таблица user/колонка password). Или ты локально без паролей? |
|
02-09-2009 12:14
02-09-2009 08:36
02-09-2009 02:50Сейчас только что проверил подключение к db4free.org(net), всё прошло успешно, данные загрузил.
Зарегистрируйся там тоже и проверь подключение.
да нет, у меня свои сервера стоят, есть на чем тестить :)
(При создании базы выбирай old_password, возможно и сейчас у тебя не коннектится к твоей из-за разниц нового и старого типов паролей).
это как? чего-то такого не нашел...
пытался и доменное имя вбивать вместо адреса - то же самое... почему последние два октета в сообщении об ошибке не соответствуют указанному адресу?
Без понятия. Единственное что могу предположить: может на базу стоит ограничение, что только с такого-то ip(или только из локальной сети) можно коннектится.
вообще-то ограничений нет. Только сейчас сообразил - это мой айпишник в сообщении об ошибке, то есть меня не пускает. Но самое интересное, что у меня на линуксе mysqlcc без проблем коннектится и никаких ошибок не выдает. В самой mysql в таблице юзеров есть запись для 'root'@'%' - я так понимаю, что это с любого айпишника можно цепляться |
|
02-09-2009 00:17сообщение от автора материала получил очень интересный глюк - host xx.xx.132.147, при подключении обламывется с ошибкой
access denied for user 'root'@'xx.xx.130.124' (using password....
Сейчас только что проверил подключение к db4free.org(net), всё прошло успешно, данные загрузил.
Зарегистрируйся там тоже и проверь подключение. (При создании базы выбирай old_password, возможно и сейчас у тебя не коннектится к твоей из-за разниц нового и старого типов паролей).
пытался и доменное имя вбивать вместо адреса - то же самое... почему последние два октета в сообщении об ошибке не соответствуют указанному адресу?
Без понятия. Единственное что могу предположить: может на базу стоит ограничение, что только с такого-то ip(или только из локальной сети) можно коннектится. |
|
01-09-2009 12:04скачал, запустил демку, локально все красиво, но когда попытался в host прописать адрес из инета, на котором крутится мускуль - получил очень интересный глюк - host xx.xx.132.147, при подключении обламывется с ошибкой
access denied for user 'root'@'xx.xx.130.124' (using password....
пытался и доменное имя вбивать вместо адреса - то же самое... почему последние два октета в сообщении об ошибке не соответствуют указанному адресу? |
|
25-08-2009 01:54сообщение от автора материала Илья: просьба писать вопросы по DataSet'ам в соответствующую ветку. |
|
24-08-2009 16:34Вот такая проблема...
Есть TdkMySqlConnection. Есть связанный с ним TdkMySqlDataSet. Есть TDBGrid, который через TDataSource связан с набором данных TdkMySqlDataSet.
Так вот.. При открытии набора данных TdkMySqlDataSet в Grid'е все текстовые поля отображаются пустыми - отображаются только BLOB и целочисленные данные. Что такое может быть? |
|
16-08-2009 02:02
15-08-2009 12:38Прилагаемый к материалу файл "Классы и демонстрационный проект" обновлён. |
|
27-07-2009 01:23сообщение от автора материала >>> нужен поиск по результату, который возвращает запрос. На основании этого поиска буду заполнять список.
TMySql - это удобная обёртка для mysql функций, не более того. Ни каких расширений функциональности я к ней писать не буду.
Вместо этого я написал потомка TDataSet'а, умеющего работать с TMySql, вот там можно искать, фильтровать, сортировать... точнее можно будет, как только его опубликуют. А пока напиши в личку e-mail я тебе его вышлю. |
|
27-07-2009 00:57riff, нужен поиск по результату, который возвращает запрос.
На основании этого поиска буду заполнять список.
|
|
27-07-2009 00:37сообщение от автора материала Билдер: Описанная тобой проблема это твоя проблема или TMуSQL?
>>>Как можно ограничить вывод значений (в идеале нужно выбрать минимальное, зная шаг и максимальное значение заполнить список и установить значение по умолчанию)?
Вот как ты сказал так и напиши у себя в программе.
>>>Нужны методы, аналогичные SetKey, GotoKey....
Какой SetKey? Какой GotoKey? Что за минимальный шаг? От куда выбрать? От куда мы взялись? (а не, последний вопрос из другой оперы). |
|
27-07-2009 00:00Использую компонент MуSQL. Таблица имеет следующую структуру:
параметр|значение_по_умолчанию|мин.|макс|шаг|
Загружаю инфо из базы в StringGrid. В StringGrid встроил ComboBox, в котором нужно отображать допустимые значения параметра. Для этого выполняю:
var
query_result : IMySQLQuery;
strSQLText : string;
begin
...
strSQLText := 'SELECT * FROM listParametr';
query_result := form1.MySQL.Query(strSQLText);
....
with form1.StringGrid1 do
begin
....
while query_result.FetchRow do
begin
Cells[0, RowCount - 1] := (query_result.ValueByName['idList']);
Cells[1, RowCount - 1] := (query_result.ValueByName['ListParametr']);
Cells[2, RowCount - 1] := (query_result.ValueByName['ParametrValue']);
ComboBox1.Items.Add(Cells[2, RowCount - 1]);
Cells[3, RowCount - 1] := (query_result.ValueByName['ParametrValueMax']);
Cells[4, RowCount - 1] := (query_result.ValueByName['ParametrValueMin']);
end;
RowCount := RowCount - 1;
end;
end;
При таком подходе в ComboBox1 отображаются все значения, хранимые в поле ParametrValue. Как можно ограничить вывод значений (в идеале нужно выбрать минимальное, зная шаг и максимальное значение заполнить список и установить значение по умолчанию)? Нужны методы, аналогичные SetKey, GotoKey. |
|
18-07-2009 05:04сообщение от автора материала ART-of-FaNtAsY:
1. Спасибо за "спасибо" :)
2. У себя на ноуте сносить MySql, чтобы проверить, не хочется, но судя по тому, что на работе народ коннектится к базе в локальной сети, то можно.
3. Напиши в личку e-mail пришлю обновление. (в королевстве задержка какая-то). |
|
18-07-2009 04:50Отличный класс.
Скажите, а можно ли использовать его для работы со встроенным сервером? Т.е. подключаться к базе данных MySQL при помощи библиотеки libmysqld.dll, не устанавливая сам сервер. |
|
04-05-2009 03:40сообщение от автора материала Кроме как проверь
* mysql.Host
* mysql.User
* mysql.Password
* mysql.Database
сказать больше ничего не могу. У меня коннектится и в localhost'те и в сети к серверной(на линуксе) и к какой-то в инете.
У mysql есть консольная оболочка, через неё коннектится? (я не жду ответа на этот вопрос :) это ты сам себя спроси.) |
|
03-05-2009 08:06MySQL поставил вместе с денвером |
|
03-05-2009 08:03На localhost все ок а по сети не могу приконектиться. Что это может быть? Фаервол отключен. Антивируса нет |
|
20-04-2009 11:38>>> Спасибо большое также riff'у за совет: сам с такой проблеммой столкнулся,
>>> весь вечер на нее убил. А все оказалось очень просто.)
За какой? Твоих вопросов (с ником Anafor) здесь не встречается.
Прошу прощения, за этот совет:
25-01-2008 08:47
Ну вот и нашли твою ошибку... Должно быть MySQL: IMySQL;
MySQL - это интерфейсная ссылка. А ты, объявив её как объект, выходя из процедуры, где её инициализируешь, просто напросто теряешь. И соответственно никаких mysql.free в конце работы не надо. И то что Один раз у тебя получается сделать селект - это чистая случайность.
Объяви как MySQL: IMySQL; и радуйся жизни. :)
|
|
11-03-2009 01:20сообщение от автора материала [i]* извините, у второго ответа форматирование сбил[/i]
Anafor:
>>> Спасибо огромное автору! Все очень удобно и продуманно.
У "компонент" два автора, кому из них "спасибо"? :-)
>>> Спасибо большое также riff'у за совет: сам с такой проблеммой столкнулся,
>>> весь вечер на нее убил. А все оказалось очень просто.)
За какой? Твоих вопросов (с ником Anafor) здесь не встречается. |
|
11-03-2009 01:16сообщение от автора материала Mike:
>>> как я понял из ответа в DBGrid (или даже SrtingGrid)
>>> нужно подставлять данные только с помощью запросов.
В DBgrid не получится т.к. он работает с TDataSet/TDataSource. А в TStringGrid, ListBox, ListView, TreeView,... пожалуйста.
>>> Можно ли при использовании MySQLClasses.pas
>>> определить значение DataSource, чтобы заполнить свойство DBGrid?
Был(есть?) такой простенький компонент что-то вроде VirtuaDataset. Он не хранит данные в себе, но по необходимости запрашивает их у тебя (т.е. в данном случае ты их отдаёшь из IMySQLQuery).
Есть подобные же (кажется TMemDataset): после выборки все данные заталкиваешь в такой потомок Dataset'а и далее уже прикручиваешь DBGrid и т.п.
Anafor:b]
>>> Спасибо огромное автору! Все очень удобно и продуманно.
У "компонент" два автора, кому из них "спасибо"? :-)
>>> Спасибо большое также riff'у за совет: сам с такой проблеммой столкнулся,
весь вечер на нее убил. А все оказалось очень просто.)
За какой? Твоих вопросов (с ником Anafor) здесь не встречается. |
|
05-03-2009 21:16>Нет нельзя, это низкоуровневая библиотека никак не связанная со >стандартными Delphi компонентами типа TDataSource.
как я понял из ответа в DBGrid (или даже SrtingGrid) нужно подставлять данные только с помощью запросов. |
|
05-03-2009 16:23Спасибо огромное автору! Все очень удобно и продуманно.
Спасибо большое также riff'у за совет: сам с такой проблеммой столкнулся, весь вечер на нее убил. А все оказалось очень просто.) |
|
05-03-2009 11:14Нет нельзя, это низкоуровневая библиотека никак не связанная со стандартными Delphi компонентами типа TDataSource. |
|
05-03-2009 09:16Уважаемые коллеги!
Можно ли при использовании MySQLClasses.pas
определить значение DataSource, чтобы заполнить свойство DBGrid? |
|
03-02-2009 11:29:DRON
да, Вы правы, это один из способов, но он повлечет за собой ненужную дисковую активность, ненужные операции записи и чтения на/с диска и, как сдедствие, общее снижение быстродействия.
В случае с recordset.getstring этого как раз удается избежать и происходит все очень быстро и четко.
Я хотел бы сделать то же самое, но еще и избавившись от ADO/ODBC, удалив еще одно лишнее звено, хотя бы применительно к MySQL.
Кстати, вы не знаете, существует ли такой нативный, без odbc, способ работы с mssql?
Сами результирующие таблицы в csv я обрабатываю в собственном табличном движке в оп.памяти и там единичные задержки радко вылезают за тот интервал, который я могу качественно измерить даже при помощи высокоточных таймеров. |
|
03-02-2009 05:21sane, почитайте про "SELECT ... INTO OUTFILE" в справке на MySQL, может оно вам и подойдёт. |
|
02-02-2009 19:50вопрос:
в ADO есть метод recordset.getstring,
позволяющий получить весь результат запроса в виде стринга, например, как csv, отформатировав результирующую табличку соответствующим образом.
как бы сделать то же самое с использованием этого компонента / получить это от libmysql другим способом?
т.е. мне нужно получить содержимое всей таблички в виде стринга/стрима/итд целиком, не дергая по ячейке/ряду. |
|
20-12-2008 09:30сообщение от автора материала * ну и естественно в конце каждой строки точка с запятой. |
|
20-12-2008 09:16сообщение от автора материала Я подобными перечислениями никогда не пользовалься, возможно это можно переписать как
type
MYSQL_SHUTDOWN_LEVEL = byte;
const
SHUTDOWN_DEFAULT: MYSQL_SHUTDOWN_LEVEL = 0;
SHUTDOWN_WAIT_CONNECTIONS: MYSQL_SHUTDOWN_LEVEL = 1,
SHUTDOWN_WAIT_TRANSACTIONS: MYSQL_SHUTDOWN_LEVEL = 2,
SHUTDOWN_WAIT_UPDATES: MYSQL_SHUTDOWN_LEVEL = 8,
SHUTDOWN_WAIT_ALL_BUFFERS: MYSQL_SHUTDOWN_LEVEL = 16,
SHUTDOWN_WAIT_CRITICAL_BUFFERS: MYSQL_SHUTDOWN_LEVEL = 17,
KILL_QUERY: MYSQL_SHUTDOWN_LEVEL = 254,
KILL_CONNECTION: MYSQL_SHUTDOWN_LEVEL = 255
если я не прав, меня поправят.
>>>[Error] MySQL.pas(136): Undeclared identifier: 'PLongWord'
type
PLongWord = ^LongWord;q |
|
19-12-2008 03:44Ну при компиляции сразу дает ошибку в модуле MySql.pas
Наверное, у вас старая версия Delphi, которая ещё не понимает перечислений с указанием значений - это оносительно недавнее расширение, появилось не то в D6, не то в D7. |
|
19-12-2008 02:07Ну при компиляции сразу дает ошибку в модуле MySql.pas:
[Error] MySQL.pas(105): ',' or ')' expected but '=' found
вот на этот кусок кода:
MYSQL_SHUTDOWN_LEVEL = (SHUTDOWN_DEFAULT = 0,
SHUTDOWN_WAIT_CONNECTIONS = 1,
SHUTDOWN_WAIT_TRANSACTIONS = 2,
SHUTDOWN_WAIT_UPDATES = 8,
SHUTDOWN_WAIT_ALL_BUFFERS = 16,
SHUTDOWN_WAIT_CRITICAL_BUFFERS = 17,
KILL_QUERY = 254,
KILL_CONNECTION = 255
);
и еще говорит: [Error] MySQL.pas(136): Undeclared identifier: 'PLongWord'
вот сздесь: return_status: PLongWord; |
|
27-11-2008 10:52сообщение от автора материала Cyber: да вроде бы ничего такого что не должно работать в Delphi5 в компоненте нет... не работает это что значит: не компилится или где? мой пример тоже не работает? какие ошибки и в каком месте.
как переделать? правильно заданный вопрос - половина ответа. |
|
27-11-2008 10:42сообщение от автора материала noname извини, твоё сообщение не видел ваше.
а ты читал ответ от 20-11-2007 11:47 может в этом дело?
|
|
27-11-2008 06:19Данный компонент не работает в Delphi5 !
как переделать?
или есть другая версия? |
|
04-11-2008 18:34Спасибо автору ,но есть пара вопросов,(извените ламера delphi), есть код
type
...
private
mysql_link: imysql;
procedure mysql_error();
end;
...
mysql_link:=TMySQL.Create;
...
mysql_link.Host:= host;
mysql_link.User:= user;
mysql_link.Password:= pass;
mysql_link.Port:= port;
if not mysql_link.Connect then mysql_error();
mysql_link.Database:= database;
...
query_str:= 'SELECT privileges.id AS `id`,'
+' privileges.user_id AS `user_id`,'
+' privileges.login AS `user_login`,'
+' privileges.add_price AS `add`,'
+' privileges.ch_price AS `change`,'
+' privileges.del_price AS `delete`,'
+' users.last_login AS `last_login`,'
+' users.prersent AS `prersent`,'
+'FROM privileges, users WHERE users.id=privileges.user_id'
+' AND users.pass = '+ u_pass;
mysql_query:= mysql_link.Query(query_str);
while mysql_query.FetchRow() do
begin
info.add('id',mysql_query.ValueByName['id']);
...
end;
но при выполнении mysql_query.FetchRow() возвращает nil. В БД всё есть, проверял запрос в консоли, всё правельно извлекаетса, авделфях нехочет, все данные или VARCHAR или INT. dll от мускуля в папке с поектом и в %SystemRoot%, что это может быть? конект к БД есть, т.к. execsql работает. А и mysql_query(mysql: pmysql; q: PChar) возвращает 0, + похожая выборка в другом месте отлично работает!
С уважением |
|
19-10-2008 17:43Большое спасибо, ч полезная весчь. |
|
08-10-2008 13:51Автору спасибо. Лучшее из того, что я видел.
Но, всё же, есть одна недоработка.
При соединении с MySQL функцией mysql_real_connect() последним параметром (флаг) передаётся 0. В результате нельзя отправить запрос CALL proc_name и вызвать процедуру, которая возвращает набор данных. Более того, почему-то в модуле mysql.pas просто нет константы CLIENT_MULTI_STATEMENTS, которую нужно передать в качестве последнего флага для того, чтобы можно было получать набор данных.
И как тут быть? Получается, эта возможность не реализована? |
|
14-08-2008 01:01Большое спасибо! Очень удобный и ОЧЕНЬ нужный компонент |
|
13-08-2008 22:12Отличный компонент! Это то, что я искал.
Всё гениально и просто!
Большое СПОСИБО автору - сэкономил мне кучу времени и нервов :) |
|
26-03-2008 10:47люди добрые дайте плиз домонстрационный проект для записи\ считывания изображений в\из базы.
будет ли отличие по скорости если использовать другие компоненты, например, myDac? |
|
09-03-2008 06:00сообщение от автора материала Скорей всего ты неверно вводишь логин или пароль или host. необязательно же у всех на локальном компе user=ODBC, у меня, например, user=root. А если ты пытаешься подключиться к удалённой mysql, то почему вводишь host=localhost, там должно быть что-то типа "217.54.2.33" (т.е. ip с которого видна база) |
|
08-03-2008 17:47этава...на моем домашнем компьютере, программа с libMysql.dll идёт и работает отлично.
на остальных - вылазит ошибка access denied for user ODBC@localhost using password - NO...вот...может там необходими еще библиотеки кроме одной? |
|
05-02-2008 22:33Я тебе отправлял дамп базы,
ты таки залей ее себе, проверь считывает ли битмап из нее
если все ок- значит у меня читает криво
если нет- значит запись кривая |
|
05-02-2008 12:31сообщение от автора материала 5.0.45 не нашёл, скачал 5.0.51а. Запустил присланный тобой тестовый проект... угадай результат... Всё работает без проблем.
Счастливчик ты наш :) |
|
05-02-2008 10:06Возможно у него чуть старше версия и может там был какой-нибудь глюк, не знаю.
У меня 5.0.45 comunity-nt |
|
04-02-2008 04:53сообщение от автора материала Попробовал ещё раз перечитать сообщение Serg. Похоже я тоже не до конца понял смысл.
Получается что-то вроде:
один наговорил текст, отправил.
у второго раз в секунду(например) программа проверяет нет ли новых сообщений, если есть воспроизводит.
?
Тогда в чём сложность? Ладно проехали. Там скорее дело техники, а не способа хранения. |
|
04-02-2008 04:30сообщение от автора материала На счёт картинки которая вызывала AV у Арсения.
Он мне прислал эту картинку и тестовый проект - я этот проект скомпилировал, запустил, добавил картинку затем её прочитал, проблем никаких нет (У меня версия MySql: Server version: 5.0.41-community-nt MySQL Community Edition). Возможно у него чуть старше версия и может там был какой-нибудь глюк, не знаю. Я пробовал запихивать различное содержание в блоб - ни разу не получилось получить некорректные данные. |
|
04-02-2008 04:29Riff, спасибо за ответ! Наверное так и должно быть - каждому софту свои задачи и нагромождать его универсальностью это, скорее всего, пойдет в ущерб основной его функциональности! Вопрос снимаю всем спасибо! |
|
04-02-2008 04:16сообщение от автора материала Возможно ли, используя MySql, осуществить голосовое общение между пользователями - аля Skype? Вот чесно скажу никогда даже случайной мысли такой не было и думать над этим нет никакого желания :)
Единственное что мелькнуло во время чтения сообщения это разрезать медиа на кусочки, записать, и затем их подгружать... записать первую часть в файл, натравить плеер, загрузить вторую часть, записать,.... (не знаю как работает плеер)
Моё мнение - не для этого нужна база, не для хранения медия и т.п. А медиа ты мог бы с тем же успехом загружать(подзагружать) и по HTTP (Indy TidHTTP). |
|
04-02-2008 04:16Geo, а как по вашему устроена работа Skype, ведь он использует сорость(интернета), которая во многих случаях еще далека от скорости сети? В нем тоже создаются эккаунты и т.д., т.е. без сервера БД, я думаю, там не обходятся. А представьте ситуацию, когда у предприятия еще нет интернет подключения, но зато есть обычная сеть, которая, как я указывал, быстрее многих интернет подключений, а рабочие места менеджеров расположены по отдельным зданиям... Просто наверное этого... никто еще не делал, тому как есть много другого ПО, которое обеспечивает данный сервис! |
|
04-02-2008 03:50>>> <...> скорость воспроизведения блобМедиаДанных меньше, чем скорость их передачи
Ну, чтобы медитаданные из блоба воспроизвести, их надо сначала в этот блоб положить. А уж пара операций (сохранение и считывание) всяко потребует больше затрат времени, чем непосредственная передача.
А в целом по вопросу... знаете, я меатериалист и считаю, что чудес на свете не бывает. А если бывает, значит мы что-то не учли. Если сервер с MySQL ухитряется вытаскивать из блоба данные и передавать их на клиента быстрее, чем клиенты обмениваются данными между собой, то это может говрить либо о качестве канала, либо о качестве механизма передачи. |
|
04-02-2008 03:38Geo, предположим, что есть проект, в котором один менеджер по продажам обнаруживает, что товар, который он хотел продать зарезервирован другим менеджером по продажам. В этом случае неплохо было бы, если предоставлялась этим проектом возможность пообщаться с ним. То, что хранилище данных..., так никто об этом и не спорит. А натолкнуло меня на этот, пусть для вас и ламерский вопрос, так это одно "наблюдение" - скорость воспроизведения блобМедиаДанных меньше, чем скорость их передачи. ТОлько, вот, как это сделать, у вы, не знаю, почему и HELP me........! |
|
04-02-2008 03:16>>> Возможно ли, используя MySql, осуществить голосовое общение между пользователями - аля Skype?
Извините, что влезаю в вашу беседу, но причем тут MySQL? MySQL -- это СУБД. Хранилище данных. Вопрос примерно того же плана, как можно ли использовать трехдюймовые дискеты для осуществления голосового общения между пользователями.
Или я неправильно понял Ваш вопрос? |
|
04-02-2008 03:08Добрый день, Riff!
Пока все..... нормально!
Извините за наглость, но у меня такой вопрос:
Возможно ли, используя MySql, осуществить голосовое общение между пользователями - аля Skype?
Как вы поняли - я в делфях еще не очень..., хотя бы подскажите посредством чего это можно решить. Ну, а если по слогам..., то это вообще - суппер было бы!
Заранее благодарю!
|
|
31-01-2008 10:44сообщение от автора материала Арсений, утром я написал тебе, что жду от тебя проблемную картинку(AV)... ну и?! |
|
31-01-2008 06:141. Не пренебрегайте чистотой кода:
if q.FetchRow() then
begin
tempStr := q.Values[0];
Эт я на скорую руку писал, уж простите..
* А ТАМ ГДЕ выскакивает ошибка - это точно bitmap? не jpeg?
Да, точно битмап. Сначала я попробовал jpeg, но потом понял, что изза этого косяк..
* ВСЕГДА ЛИ эта картинка является проблемной? т.е. нет такого что сейчас открылась, а в другой раз AV?
Да, всегда.. если вылетает AV- то всегда вылетает. Если работает- всегда работает.
то загружет битмап, но какой то поврежденный
Это вообще интересно выглядит... картинка из базы загружается с потерей некоторых цветов... Я вообще удивился..
(Вот такая поврежденная картинка- это стандартная виндовозовская "ЦИНОВКА") |
|
31-01-2008 00:34сообщение от автора материала иначе создай новый проект, ... блин, не дописал. Ну естественно пришли мне его(сурсы). |
|
31-01-2008 00:30сообщение от автора материала 1. Не пренебрегайте чистотой кода:
q:=mysql.Query('SELECT blobfield FROM test.t1 WHERE ID=1');
if q=nil then
begin
memo1.Text := Format('Ioeaea #%d '#13#10' %s', [MySQL.ErrorCode, MySQL.ErrorMessage]);
Exit;
end;
if q.FetchRow() then
begin
tempStr := q.Values[0];
....
2. Сейчас, скорей всего, ошибка не из-за этого....
* А ТАМ ГДЕ выскакивает ошибка - это точно bitmap? не jpeg?
* ВСЕГДА ЛИ эта картинка является проблемной? т.е. нет такого что сейчас открылась, а в другой раз AV?
* Если картинка ВСЕГДА проблемная, то пришли мне ЕЁ, иначе создай новый проект, сделай там только коннект, вставку/чтение записи, пару-тройку тестовых картинок и sql комманду "create table ..." в которой тестируешь. (Сам только сначала протестируй чтобы гарантированно получался AV) (также вложи свою версию libmysql.dll и mysql.pas/mysqlclasses.pas). |
|
30-01-2008 13:27p.s. Арсений, у тебя-то хоть записываются/считываются?
записываются :)
но не считываются... что я неправильно сделал не знаю, но:
когда записывается- всегда без проблем,
когда считывается- то вылетает AV(на месте LoadFromStream), то Вылетает "Invalid Bitmap Data.."(или чтото такое), то загружет битмап, но какой то поврежденный, а иногда- все нормально, как записал, так и считал без ошибок.
Вариант ошибки зависит от файла.. одну bmp нормально сохраняет, другую криво.. :(
Вот две процедуры:
procedure TForm1.Button8Click(Sender: TObject);
var
a, b: string;
s: TMemoryStream;
i:integer;
begin
s:=TMemoryStream.Create;
img.Picture.Bitmap.SaveToStream(s);
s.Position := 0;
try
SetLength(a, s.size);
s.Read(pointer(a)^, length(a));
finally
s.Free;
end;
SetLength(b, length(a)*2);
i:=mysql_real_escape_string(MySQL.MySQL, Pointer(b), Pointer(a), length(a));
SetLength(b, i);
if mysql.ExecSQL('REPLACE INTO test.t1(ID,blobfield) VALUES (1,'''+b+''')') then showmessage('OK')
Else
memo1.Text := Format('Ioeaea #%d '#13#10' %s', [MySQL.ErrorCode, MySQL.ErrorMessage]);
end;
procedure TForm1.Button9Click(Sender: TObject);
var
tempStr: string;
stream: TMemoryStream;
q: IMySQLQuery;
begin
q:=mysql.Query('SELECT blobfield FROM test.t1 WHERE ID=1');
if q=nil then
memo1.Text := Format('Ioeaea #%d '#13#10' %s', [MySQL.ErrorCode, MySQL.ErrorMessage]);
WHILE q.FetchRow() Do
tempStr := q.Values[0];
stream := TMemoryStream.Create;
try
stream.Write(Pointer(tempStr)^, Length(tempStr));
stream.Position := 0;
img.Picture.Bitmap := TBitmap.Create;
img.Picture.Bitmap.LoadFromStream(stream);
finally
stream.free;
end;
end;
|
|
30-01-2008 10:33Все Ок!!!!!!!!!!!!!!!!!!!!!!!!!
Riff? вы гений!
Оказывается я невнимательно все читал!
Спасибо вам большое, свою "функцию" я уже выбросил! |
|
30-01-2008 09:52сообщение от автора материала давай по слогам разбираться:
20-11-2007 11:47
в файле MySql.pas заменить описание этой функции:
...
function mysql_fetch_lengths(result: pmysql_res): Pointer; stdcall;
...
implementation
...
function mysql_fetch_lengths(result: pmysql_res): Pointer; stdcall; external libmySQL;
...
в файле MySQLClasses.pas заменить
function TMySQLQuery.GetValues(FieldNo: Integer): string;
на функцию
из ответа 20-11-2007 11:47
Каково было мое удивление, когда я понял, что в блобе оказывается не экранированные данные после mysql_real_escape_string, а изначальные, как до экранирования(var а). Т.е. сервер преобразовал их в изначальный вид И ЭТО ПРАВИЛЬНО. ТАК И ДОЛЖНО БЫТЬ.
Т.е. билет в одну сторону, чтобы читать назад..., нужен новый "билет". Нет, ничего больше не нужно. просто select * from mytable.
Полученную строку из стрима экранирую, но не mysql_real_escape_string, а своей функцией, от проблемных символов и передаю ее в блоб простым MySql запросом. выброси свою функцию. делай только так как я расписывал ранее.
действуй. я сегодня уже врятли отвечу. до завтра.
p.s. Арсений, у тебя-то хоть записываются/считываются? |
|
30-01-2008 08:51var
a, b: string;
fs: TFileStream;
begin
fs := TFileStream.Create('myfile.bmp', fmOpenRead or fmShareDenyWrite);
try
SetLength(a, fs.size);
fs.Read(pointer(a)^, length(a));
finally
fs.Free;
end;
SetLength(b, length(a)*2);
i:=mysql_real_escape_string(MySQL.MySQL, Pointer(b), Pointer(a), length(a));
SetLength(b, i);
end;
Riff, все правильно, но я постараюсь объяснить - почему я назвал эту функцию(mysql_real_escape_string) односторонней:
Каково было мое удивление, когда я понял, что в блобе оказывается не экранированные данные после mysql_real_escape_string, а изначальные, как до экранирования(var а). Т.е. сервер преобразовал их в изначальный вид, что и делает эту функцию односторонней. Т.е. билет в одну сторону, чтобы читать назад..., нужен новый "билет". Извините за отвлечение, но если не купить новый билет, то в результате, как я указывал ранее, при чтении картинки в query_result.ValueByName['image'] мы максимум, что получаем, так это 4 символа, например, 'яШяа' и все. Очевидно, сервер спотыкается при первой встрече с управляющими(или проблемными для него) символами. Еще я заметил эти первые 'яШяа' у каждого типа картинок свои, например, вышеуказанный относится к '*.jpg'. Может на стороне сервера и есть какие либо методы(билет) типа mysql_real_escape_string, но я о них, к своему стыду, ничего не знаю.
На данный момент, чтобы решить эту проблему я делаю так:
Полученную строку из стрима экранирую, но не mysql_real_escape_string, а своей функцией, от проблемных символов и передаю ее в блоб простым MySql запросом. В результате в блобе оказываются данные, которые при их чтении легко располагаются во все том же query_result.ValueByName['image'], поскольку не содержат клятых проблемных.... Вы правильно заметите, что в таком случае query_result.ValueByName['image'] не есть картинка и будете правы. Поэтому приводим ее в первоначальное состояние деэкранированием - функция обратная функции экранирования.
Я не считаю свой метод правильным, да и согласен с вами, что SQL запрос небезразмерен, поэтому к вам просьба:
Если у вас получилось ЧИТАТЬ картинку другими методами, просьба показать примерчик.
Спасибо за ответы!
|
|
30-01-2008 05:22сообщение от автора материала но теперь, в свете написанного ниже все встало на свои места и прояснилось. есть новость и совет. не берусь сказать плохие они или нет... так себе.
Не смотря на размер данных, способное вместить блоб поле, вам врятли удастся передать в sql комманде данные большого размера. (у меня сейчас получилось картинку вместить что-то около 500кило).
Может это где-то в настройках меняется, может ещё как-то - незнаю.
Совет: хранить картинки или другие бинарные данные в блобе не есть хорошо вообще, и гонять их по сетке "select * from mytable" в часности. их надо сваливать в отдельную папочку и передавать только по желанию. (имена же им давать "уникальный_номер_записи.расширение") |
|
30-01-2008 04:54Извините, что не отвечал, просто не было времени заглянуть на страничку.
Спасибо за замечания, сейчас буду пытаться воплотить ваши пожелания. О результатах обязательно сообщу. |
|
30-01-2008 04:51сообщение от автора материала Такого вопроса небыло, но, возможно, у кого-то всплывёт эта "проблемка".
MySQL хранит дату в формате год-месях-день, что правильно с точки зрения сортировки, россиянам привычней читать на экране дату в формате день.месяц.год
var
FormatSettings: TFormatSettings;
Date: TDateTime;
begin
FormatSettings.ShortDateFormat := 'yyyy-mm-dd';
FormatSettings.LongDateFormat := 'yyyy-mm-dd';
FormatSettings.DateSeparator := '-';
date := StrToDate('1970-05-10', FormatSettings);
...
str := DateToStr(date);
str := DateToStr(date, FormatSettings);
end; |
|
30-01-2008 04:19Очередной раз большое спасибо, riff!
Теперь все доступно и понятно...
Я просто не понимал, как к запросу приклеить string с бинарными данными к SQL запросу...
Про экранирование и использование hex- очень к месту совет..
По поводу красного словца: прошу меня простить, я подобрал не то выражение, какое следовало бы..
Просто пример был мне не понятен, но теперь, в свете написанного ниже все встало на свои места и прояснилось. :) |
|
30-01-2008 02:43сообщение от автора материала Если у кого то есть готовые функции для записи/чтения потока из блоба, то отпостите их, пожалуйста... Вчера же чёрным по серому написал чтение из блоба в поток, с последующим выводом в timage и в файл "29-01-2008 05:18". |
|
30-01-2008 02:31сообщение от автора материала Теперь по поводу: Функция mysql_escape_string не подходит, так как односторонняя. ты просто не умеешь её готовить...
var
a, b: string;
fs: TFileStream;
begin
fs := TFileStream.Create('myfile.bmp', fmOpenRead or fmShareDenyWrite);
try
SetLength(a, fs.size);
fs.Read(pointer(a)^, length(a));
finally
fs.Free;
end;
SetLength(b, length(a)*2);
i:=mysql_real_escape_string(MySQL.MySQL, Pointer(b), Pointer(a), length(a));
SetLength(b, i);
end;
INSERT INTO ... VALUES (..., "' + b + '") |
|
30-01-2008 02:13сообщение от автора материала Если честно, я вообще очень смутно представляю, как можно передать последовательность байтов..
function StrToHex(const Text: String): String;
begin
if Text = '' then
begin
Result := '';
Exit;
end;
SetLength(Result, Length(Text) * 2);
BinToHex(Pointer(Text)^, Pointer(Result)^, Length(Text));
end;
Считываешь в строку данные из файла. превращаешь строку в hex с помощью этой функции.
Ведь в этой последовательности может быть и нулевой символ.. у строки(string) нет ограничения на символы. |
|
30-01-2008 01:58сообщение от автора материала Я так понимаю, чтение из блоба, хоть и через пень-колоду, все таки реализуется.. Ради красного словца, не пожалеем...
А чем вас не устроило чтение из блоба? Вы не знаете что делать с полученной строкой? |
|
30-01-2008 01:36сообщение от автора материала Все работает, если предварительно кодировать картинку от проблемных символов, а затем, соответственно, декодировать. Ну, наверно не кодировадь, а при вставке экранировать? надо просто в мануале почитать какие символы и как экранируются (например #0->\0, #10->\r, #13->\n), там их не много. А декодировать ничего не надо...
Написал свою, немного увеличивает объем данных, зато все без проблем работает. Т.е. в итоге в блобе информации больше чем нужно? ~:| См.выше.
Тогда все Ок. Иначе после фетча query_result.ValueByName['image'] дает только первых несколько бряков, которые, как я понял не проблемные. Скорей всего ты в данном случае не прав. ValueByName должна возвращать строку не смотря на то какие там символы.
Например PhpMyAdmin при эспорте позволяет записывать блох в шестнадцатеричное отображении ну т.е. в HEX.
В Delphi есть функция BinToHex(кажется называется), которая превратит все символы переданного ей буфера в hex последователности и твой insert превратиться что-то подобное
INSERT INTO `book` (`pid`, `first_name`, `last_name`, `dr`, `phone`, `address`, `image`) VALUES
(1, 'Имя 1 2', 'Фамилия 1 2', '1970-02-02', '123-45-62', 'Город: ABC; улица: DEF; дом: 2', 0x424d3a1703000)
где 0x424d3a1703000 это
* 0x начало данных - это ты вставляешь сам
* 424d3a... - сами данные "BM:..." - это твоя картинка ввиде hex строки
ничего экранировать не надо, кавычек не надо, извлекаются данные также как я писал в пред.постах. |
|
30-01-2008 00:22Вопрос с блобами меня также все еще интересует... мало того, я до сих пор не знаю, как записать стрим в блоб...
и как я понял, со считыванием обратно тоже какие то проблемы...
Я в работе с разного рода указателями , памятью и тд не мастак, поэтому слегка парюсь..
Если у кого то есть готовые функции для записи/чтения потока из блоба, то отпостите их, пожалуйста...
Ежели ни у кого нету, то давайте писать вместе...
Я так понимаю, чтение из блоба, хоть и через пень-колоду, все таки реализуется..
Я вопрос о блобах задавал собственно автору этих компонент(Виталию Лещенко), которые были потом чуть чуть изменены автором этой статьи...
Вот цитата из его ответа:
Работа с блобами и другими бинарными данными требует дополнительных действий.
Эти действия выполняются с помощью методов:
function BinaryToString(const p: Pointer; size: Integer): string;
procedure StringToBinary(const s: String; p: Pointer; out size: Integer);
Видимо речь шла как раз о том, что и сделал своими руками уважаемый Serge
Если честно, я вообще очень смутно представляю, как можно передать последовательность байтов..
Что, прямо внутри SQL-запроса?
Ведь в этой последовательности может быть и нулевой символ..
Теперь вы меня извиняйте за ламерские вопросы... ну не понимаю я технологию.. |
|
29-01-2008 13:52Извините, но опять по поводу картинки из bloba!
var
tempStr: string;
stream: TMemoryStream;
begin
tempStr := query_result.ValueByName['image']; //предположим ваш blob называется image
stream := TMemoryStream.Create;
try
stream.Write(Pointer(tempStr)^, Length(tempStr));
stream.Position := 0; // не забывайте обнулять позицию stream
//отобразим в TImage
Image1.Picture.Bitmap := TBitmap.Create;
Image1.Picture.Bitmap.LoadFromStream(stream);
//сохраним на диске
stream.Position:=0;
stream.SaveToFile('c:\b.bmp');
finally
stream.free;
end;
end;
Все работает, если предварительно кодировать картинку от проблемных символов, а затем, соответственно, декодировать. Тогда все Ок. Иначе после фетча query_result.ValueByName['image'] дает только первых несколько бряков, которые, как я понял не проблемные. Функция mysql_escape_string не подходит, так как односторонняя. Написал свою, немного увеличивает объем данных, зато все без проблем работает. Пишу это все потому, как думаю, что "зубы почистил через нос", не верится, что такой инструмент с блобами проще не работает. Скорее всего я просто не знаю, как это... сделать. Если кто знает просьба примерчик. |
|
29-01-2008 07:16Арсений, еще раз благодарю вас! Я приобрел - MySql Поль Дюбуа третье издание, но с удовольствием воспользуюсь вашими источниками. |
|
29-01-2008 07:14PS: Serge, ты меня на 4 года старше... думаю обращение "на ты" будет вполне уместным))))))))) |
|
29-01-2008 07:10:) Да я сам неделю назад первый раз столкнулся с Мускулом.. Сам ламер из ламеров...
Я собственно в основном всю информацию беру из двух книжек.. где скачал не помню, но думаю, найдешь..
1)MySQL БИБЛИОТЕКА ПРОФЕССИОНАЛА, ЛЕОН АТКИНСОН (файл в pdf'е, написана очень доступно, легко и интересно читается, полно примеров, НО это про 3 версию мускула)
2)MySQL, Поль Дюбуа (djvu, немного тяжелее читать, но зато это про 4 версию..)
Про 5 версию нашел только одну книгу, и то только в интернет-магазине, называется "Самоучитель MySQL 5"
ссылка: http://www.softtime.ru/sql/?id_article=84
ну и конечно же справку по мускулу читать надо... там вполне нормальный поиск |
|
29-01-2008 06:52Арсений, большое спасибо!
Я все понял, извините за ламерские вопросы, буду учить матчасть. |
|
29-01-2008 06:48ПРОЦЕДУРЫ НЕ ВОЗВРАЩАЮТ НИЧЕГО!
можно использовать выходные параметры, для того чтобы например указать что произошло: вставилась строка, или уже существовала строка с таким кодом и была обновлена, или не была обновлена..
Считать выходной параметр можно так:
Например, вызвали процедуру, указав ей переменную для выходного параметра
CALL proc_name(@variable)
Тогда чтобы узнать значение переменной, вызовем
SELECT @variable; |
|
29-01-2008 06:39ХП:
CREATE PROCEDURE `SelBook`(in id varchar(100))
BEGIN
Drop table if exists mydb_test.TempBook;
Create temporary table if not exists mydb_test.TempBook Select * from mydb_test.Book where `pid`=id;
END
Вызов:
MySQL.Query('CALL SelBook('+ GroupData.id+')');
query_result := MySQL.Query('select * from `TempBook` where `pid`=' + GroupData.id);
Если есть способ более простой и быстрый, прошу сообщить.
Заранее благодарю!
хм.. по моему тебе нужна не процедура, а VIEW. Эт типа запроса, хранимого в СУБД..
Создается "CREATE VIEW `view_name` AS SELECT * FROM table_name;"
Запускается "SELECT * FROM view_name"
стореды нужны, как я понял для того, чтобы например добавлять информацию в базу или изменять ее..
вот например у меня такая процедура:
(для пополнения/изменения списка товаров на складе)
CREATE DEFINER=`root`@`localhost` PROCEDURE `goods_add`(ID smallint, nm char(45), unit_snm char(3))
BEGIN
IF ID IS NOT NULL THEN
INSERT INTO goods(IDgoods,name,IDunit,`count`) VALUES (ID,nm,(SELECT IDunit FROM unit WHERE shortname=unit_snm),0)
ON DUPLICATE KEY UPDATE name=nm, IDgoods=ID;
ELSE
INSERT INTO goods(name,IDunit,`count`) VALUES (nm,(SELECT IDunit FROM unit WHERE shortname=unit_snm),0);
END IF;
END
ПРОЦЕДУРЫ НЕ ВОЗВРАЩАЮТ НИЧЕГО!
для этого, на крайняк, есть функции:
(функция проверяет совместимость единиц измерения. Например килограмм и грамм совместимы- обе весовые, возвратит 1, а если разные типы, то значит несовместимы, следовательно 0)
CREATE DEFINER=`root`@`localhost` FUNCTION `unit_type_equal`(IDunit1 SMALLINT, IDunit2 SMALLINT) RETURNS tinyint(1)
BEGIN
RETURN (SELECT IDunittype FROM unit WHERE IDunit=IDunit1)=(SELECT IDunittype FROM unit WHERE IDunit=IDunit2);
END
|
|
29-01-2008 05:42Большое спасибо!
Теперь я понял - почему у меня не получалось... |
|
29-01-2008 05:18сообщение от автора материала Извините за назойливость, но у меня к вам еще один вопросик:
Что-то у меня не получается вытящить картинку с Bloba.
1. ВНИМАТЕЛЬНО смотрим какие блобы сколько информации вмещают.
2. Внимательно смотрим обсуждение ниже и делаем соответствующие изменения в коде. (Номера вопроса/ответа я только что давал Арсению, но всё равно прочитайте всё чтобы не спрашивать где что менять).
3.
var
tempStr: string;
stream: TMemoryStream;
begin
tempStr := query_result.ValueByName['image'];
stream := TMemoryStream.Create;
try
stream.Write(Pointer(tempStr)^, Length(tempStr));
stream.Position := 0;
Image1.Picture.Bitmap := TBitmap.Create;
Image1.Picture.Bitmap.LoadFromStream(stream);
stream.Position:=0;
stream.SaveToFile('c:\b.bmp');
finally
stream.free;
end;
end; |
|
29-01-2008 04:00Автор пишет:
P.S. А чем твоя конструкция с ХП отличается от просто
query_result := MySQL.Query('select * from `book` where `pid`=' + GroupData.id);
Извините, если ввел вас в недоумение. Просто забыл пояснить, что я хотел попробовать работу с ХП, а сточки зрения целесообразности, вы абсолютно правы, что в вашем коде эта(ХП) лишний хвост.
Извините за назойливость, но у меня к вам еще один вопросик:
Что-то у меня не получается вытящить картинку с Bloba.
Если не трудно дайте примерчик. |
|
28-01-2008 10:21сообщение от автора материала Serge: Если есть способ более простой и быстрый, прошу сообщить. Не совсем понятно что вообще-то хочешь в итоге получить и что именно хочешь упростить. Компонент хранимые процедуры, можно сказать поддерживает - т.к. хп выполняются точно также посылкой правильной sql команды. Если возвращение данных не предпологается, то вместо MySQL.Query лучше вызывать MySQL.execSQL. Скорость зависит от твоих знаний sql, но, извини, т.к. к работе компонента этот вопрос не имеет отношения, то лучше его(вопрос) точней сформулировать и задать в форуме.
P.S. А чем твоя конструкция с ХП отличается от просто query_result := MySQL.Query('select * from `book` where `pid`=' + GroupData.id); я чего-то не догнал... |
|
28-01-2008 09:41По моему выкрутился, т.е. если применять ХП, то последовательность должна быть такая:
ХП:
CREATE PROCEDURE `SelBook`(in id varchar(100))
BEGIN
Drop table if exists mydb_test.TempBook;
Create temporary table if not exists mydb_test.TempBook Select * from mydb_test.Book where `pid`=id;
END
Вызов:
MySQL.Query('CALL SelBook('+ GroupData.id+')');
query_result := MySQL.Query('select * from `TempBook` where `pid`=' + GroupData.id);
Если есть способ более простой и быстрый, прошу сообщить.
Заранее благодарю!
|
|
28-01-2008 08:59Спасибо за ответ!
Создана ХП:
CREATE PROCEDURE `SelBook`(In id varchar(100))
BEGIN
Select * from book where `pid`=id;
END
вызываю:
query_result := MySQL.Query('CALL SelBook('+ GroupData.id+')');
Выдает:
Ошибка - процедура SelBook не может возвратить результат
Подскажите, пожалуйста, что я не так... делаю?
|
|
28-01-2008 08:39Если процедура создана, то запросом "CALL proc_name(par_in, @par_out);" (proc_name -имя процедуры,par_in- входной параметр, @par_out- переменная, выходной параметр), по моему так..
|
|
28-01-2008 08:01Все хорошо работает, спасибо автору!
Я еще, можно сказать, учусь работать в Delphi, поэтому вопросик:
Подскажите, пожалуйста, как, используя эти инструменты, можно вызвать хранимую процедуру с ВХОДНЫМИ и ВЫХОДНЫМИ параметрами? Было бы супер, если с примерчиком.
|
|
26-01-2008 05:36сообщение от автора материала ЕСЛИ при выпонении на одном из этапов execsql вернул false наверно неточно выразился, если на каком-то этапе ты решил не сохранять сделанные изменения, то откатить. Так будет точнее. |
|
26-01-2008 05:30сообщение от автора материала Подскажите, поддерживает ли он транзакции? Вобщем мне нечего добавить к ответу Арсения. Просто посмотри в мануале какой тип базы что может. Как это осуществить в программе? Посылаешь sql команды (MySql.ExecSql('...')) начать транзакцию, что-то выполнить, ЕСЛИ при выпонении на одном из этапов execsql вернул false откатить тразакцию, иначе подтвердить. |
|
26-01-2008 02:31По моему, трунзакции поддерживает не компонент, а сервер MySQL
Компонент просто передает SQL-код северу, и если нужно, возвращает результат..
MySQL не поддерживает транзакции для стандартного типа таблиц (MyISAM),
так же для него не поддерживается ссылочная целостность.
Зато производительность обработки запросов к этому типу таблиц очень высока.
А вот для раширенного типа таблиц (например InnoDB) поддерживается и то и то.(конечно в ущерб производительности)
Как использовать транзакции?
Для начала почитай мануал к серверу.. я сам не использовал пока, но по моему с помощью комманд "SET TRANSACTION"(?) "BEGIN" "COMMIT" "ROLLBACK" |
|
26-01-2008 00:56Добрый день.
Посмотрел на компонент с примером. Легко, понятно.
Подскажите, поддерживает ли он транзакции? Как это осуществить в программе? |
|
25-01-2008 09:08сообщение от автора материала с блобами работать возможно?
Кажется да, "кажктся" потому что на 100% не тестировал.
Посмотри:
* Вопрос: 20-11-2007 08:55
* Ответ: 20-11-2007 11:47 |
|
25-01-2008 08:57Спасибо большое! Вы мне очень помогли!
Последний вопрос:с блобами работать возможно? :) |
|
25-01-2008 08:55сообщение от автора материала может у меня старая версия компонент? Я пользуюсь той же версией что и на сайте. Единственное версию libmysql.dll взял из своей версии mysql, но проверил твой вопрос с той версией библиотеки что на сайте - работает. |
|
25-01-2008 08:47сообщение от автора материала Ну вот и нашли твою ошибку... Должно быть MySQL: IMySQL;
MySQL - это интерфейсная ссылка. А ты, объявив её как объект, выходя из процедуры, где её инициализируешь, просто напросто теряешь. И соответственно никаких mysql.free в конце работы не надо. И то что Один раз у тебя получается сделать селект - это чистая случайность.
Объяви как MySQL: IMySQL; и радуйся жизни. :) |
|
25-01-2008 08:40ах да, простите.. :)
var mysql:TMysql; |
|
25-01-2008 08:21сообщение от автора материала mysql:=TMysql.create(); по моему так... это не объявление, а инициялизация :) а вот
var
I: Integer;
это объявление.
|
|
25-01-2008 08:18mysql:=TMysql.create(); по моему так... |
|
25-01-2008 06:33сообщение от автора материала Блин(это я себе. такую же, скорей всего ошибку допустил), Арсений, у тебя как переменная MySQL объявлена? |
|
25-01-2008 06:23сообщение от автора материала Арсений:
Чёто и у меня глюки полезли... сейчас, подожди, разберусь. |
|
25-01-2008 05:31кажись забыл строку выделенную жирным. она должна быть до обращения к таблицам или так "select * from db.t1"
У меня есть кнопка OpenDB:
procedure TForm1.Button5Click(Sender: TObject);
begin
MySQL.Database := 'DB';
CheckBox4.Checked:=MySQL.Database = 'DB';
if MySQL.Database <> 'DB' then
begin
Caption := Format('#%d - %s', [MySQL.ErrorCode, MySQL.ErrorMessage]);
Exit;
end;
MySQL.ExecSQL('SET CHARSET cp1251');
end;
Я не могу понять, почему у меня после первого же запроса на селект соединение с сервером разрывается?
с другими запросами все в порядке. (правда, апдейт я не проверял еще)
может у меня старая версия компонент? |
|
25-01-2008 03:55сообщение от автора материала Василий Болгар:
Действительно. Назовём его недочётом т.к. в коде используется переменная FHost а не property Host, так что на внутреннюю работу это не влияет. |
|
25-01-2008 03:51сообщение от автора материала Арсений:
В твоём коде ничего не менял. Сделал следующее:
procedure TForm2.FormCreate(Sender: TObject);
begin
MySQL := TMySQL.Create;
MySQL.Host := 'localhost';
MySQL.Port := 3306;
MySQL.User := '...';
MySQL.Password := '...';
checkbox1.Checked:=MySQL.Connect;
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
checkbox2.Checked:=MySQL.ExecSQL('CREATE DATABASE как у тебя');
mysql.Database := 'DB';
checkbox5.Checked:=
MySQL.ExecSQL('CREATE TABLE `T1` как у тебя');
checkbox6.Checked:=
MySQL.ExecSQL('CREATE TABLE `T2` как у тебя');
end;
procedure TForm2.Button2Click(Sender: TObject);
var
s:string;
i: Integer;
begin
s:='INSERT INTO T1 как у тебя';
for i:=1 to memo1.Lines.Count-1 do
s:=s+',('''+memo1.Lines[i]+''')';
CheckBox7.Checked:=MySQL.ExecSQL(s);
s:='INSERT INTO T2 как у тебя';
for i:=1 to memo2.Lines.Count-1 do
s:=s+',('''+memo2.Lines[i]+''',1)';
for i:=0 to memo3.Lines.Count-1 do
s:=s+',('''+memo3.Lines[i]+''',2)';
CheckBox8.Checked:=MySQL.ExecSQL(s);
end;
procedure TForm2.Button3Click(Sender: TObject);
var
q: IMySQLQuery;
i:integer;
begin
q:=mysql.Query('SELECT * FROM T1');
end;
procedure TForm2.Button4Click(Sender: TObject);
var
q: IMySQLQuery;
i:integer;
begin
q:=mysql.Query('SELECT * FROM T2');
end;
Нажимаю кнопки подряд - всё Ok.
та кажись забыл строку выделенную жирным. она должна быть до обращения к таблицам или так "select * from db.t1" |
|
24-01-2008 05:19Нашел! Ошибка здесь, в "MySqlClasses.pas".
function TMySQL.GetDatabase: string;
begin
Result := FDatabase;
end;
function TMySQL.GetHost: string;
begin
Result := FDatabase;
end;
|
|
24-01-2008 05:13Я не часто в Инете сижу, но сюда захожу. Пользуюсь компонентом mysql. Спасибо!
Я не знаю, но в скачанной мной версии (месяца 2 назад скачал) есь такая ошибка
function Блаблабла.GetHost:String;
begin
Result:=FDatabase;
end;
Описал не точно, а на память, сейчас просто я не дома.
|
|
24-01-2008 04:59простите за отдельные посты- в один все не влезло((( |
|
24-01-2008 04:58Я создаю дочернюю таблицу:
checkbox6.Checked:=
MySQL.ExecSQL('CREATE TABLE `T2` ('+
'id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, ' +
'text VARCHAR( 25 ) NOT NULL, ' +
'idT1 SMALLINT UNSIGNED NOT NULL, ' +
'FOREIGN KEY (idT1) REFERENCES T1(id) '+
'ON DELETE CASCADE '+
'ON UPDATE CASCADE '+
') ENGINE = InnoDB CHARACTER SET cp1251 COLLATE cp1251_general_ci');
Я заполняю родительскую таблицу из Мемо:
s:='INSERT INTO T1 (name) VALUES ('''+memo1.Lines[0]+''')';
for i:=1 to memo1.Lines.Count-1 do
s:=s+',('''+memo1.Lines[i]+''')';
CheckBox7.Checked:=MySQL.ExecSQL(s);
Я заполняю дочернюю из двух мемо(в первом мемо всего две записи):
s:='INSERT INTO T2 (text,idT1) VALUES ('''+memo2.Lines[0]+''',1)';
for i:=1 to memo2.Lines.Count-1 do
s:=s+',('''+memo2.Lines[i]+''',1)';
for i:=0 to memo3.Lines.Count-1 do
s:=s+',('''+memo3.Lines[i]+''',2)';
CheckBox8.Checked:=MySQL.ExecSQL(s);
____________________________________________
до сих пор все работает нормально, без проблем
Но вот после всех этих стараний я решил сделать выборки из таблиц.
Сделал два идентичных запроса:
К родительской:
var
q: IMySQLQuery;
i:integer;
begin
q:=mysql.Query('SELECT * FROM T1');
if q=nil then
Caption := Format('%d - %s', [MySQL.ErrorCode, MySQL.ErrorMessage])
else
begin
sg.ColCount:=q.FieldCount;
sg.RowCount:=q.RecordCount;
while q.FetchRow() do
begin
for i:=0 to q.FieldCount-1 do
sg.Cells[i,q.RecNo]:=q.Values[i];
end;
end;
end;
И к дочерней:
var
q: IMySQLQuery;
i:integer;
begin
q:=mysql.Query('SELECT * FROM T2');
if q=nil then
Caption := Format('%d - %s', [MySQL.ErrorCode, MySQL.ErrorMessage])
else
begin
sg.ColCount:=q.FieldCount;
sg.RowCount:=q.RecordCount;
while q.FetchRow() do
begin
for i:=0 to q.FieldCount-1 do
sg.Cells[i,q.RecNo]:=q.Values[i];
end;
end;
end;
Это все была призказка,
теперь, собственно, сама проблема:
Когда я делаю запрос на выборку(любой из двух), все проходит нормально, stringgrid заполняется информацией.
Но после этого ни один запрос не работает:
если я сделаю второй запрос на выборку, то он возвращает NIL с неизвестной ошибкой и 8-значным кодом...
если я попробую отправить INSERT-запрос, вылетает Access Violation..
работает только Disconnect
Но после повторного коннекта и открытия бд запрос на выборку тоже вылетает в Access Violation...
Что я сделал не так? Любые советы(не только по заданному вопросу, но и вцелом по процитированному коду) будут приняты с преввеликою благодарностию))) |
|
24-01-2008 04:57Здраствуйте, уважаемые!
Проблема такова:
Я постарался сделать все почти как в предложенном примере(за исключением того, что я выбрал движок иннодб и сделал связь с проверкой целостности)
И у меня почти :( получилось:
Я соединяюсь с сервером:
MySQL.Host := 'localhost';
MySQL.Port := 3306;
MySQL.User := '';
MySQL.Password := '';
checkbox1.Checked:=MySQL.Connect;
Я создаю базу:
checkbox2.Checked:=MySQL.ExecSQL('CREATE DATABASE `DB` DEFAULT CHARACTER SET CP1251');
Я создаю родительскую таблицу:
checkbox5.Checked:=
MySQL.ExecSQL('CREATE TABLE `T1` ('+
'`id` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, ' +
'`name` VARCHAR( 25 ) NOT NULL' +
') ENGINE = INNODB CHARACTER SET cp1251 COLLATE cp1251_general_ci');
|
|
20-11-2007 11:47сообщение от автора материала Или вот так:
function mysql_fetch_lengths(result: pmysql_res): Pointer; stdcall;
function mysql_fetch_lengths(result: pmysql_res): Pointer; stdcall; external libmySQL;
function TMySQLQuery.GetValues(FieldNo: Integer): string;
var
lengths: Pointer;
length: Integer;
begin
if FRow <> nil then
begin
Lengths := mysql_fetch_lengths(FRes);
if Lengths <> nil then
begin
length := PCardinal(LongInt(Lengths) + FieldNo * SizeOf(Cardinal))^;
SetLength(Result, length);
Move(FRow[FieldNo]^, Pointer(Result)^, length);
end else
Result := '';
end else
Result := '';
end; |
|
20-11-2007 11:34сообщение от автора материала А, нет не надо изменять описания функций - это я нитуда посмотрел. и соответственно
var
Fl: LongWord; в функции GetValues |
|
20-11-2007 11:29сообщение от автора материала Попробуй
1. Исправь соответствующие описания функций:
function mysql_fetch_lengths(result: pmysql_res): PLongWord; stdcall;
function mysql_fetch_lengths(result: pmysql_res): PLongWord; stdcall; external libmySQL;
2. замени
function TMySQLQuery.GetValues(FieldNo: Integer): string;
begin
if FRow <> nil then
Result := StrPas(FRow[FieldNo]);
end;
на
function TMySQLQuery.GetValues(FieldNo: Integer): string;
type
TCA = array of LongWord;
var
Fl: PLongWord;
begin
if FRow <> nil then
begin
Fl := mysql_fetch_lengths(FRes);
SetLength(Result, TCA(Fl)[FieldNo]);
Move(FRow[FieldNo]^, Pointer(Result)^, TCA(Fl)[FieldNo]);
end;
end;
Вся информация будет возвращаться в результирующей строке. Это я на 100% не проверял, сделал на скорую руку. |
|
20-11-2007 08:55Господа, А как с помощью этого компонента работать с БЛОБ полями? Сообщение не подписано |
|
06-10-2007 03:49сообщение от автора материала MySQL.ExecSQL('SET CHARSET cp1251'); видимо надо(правильнее) писать после того как подключился к какой-либо базе, а не просто к mysql. т.е. ещё раз
либо
MySQL.Host :=
MySQL.Port :=
MySQL.User :=
MySQL.Password :=
MySQL.Database :=
if MySQL.Connect then
begin
MySQL.ExecSQL('SET CHARSET cp1251');
end;
либо
MySQL.Host :=
MySQL.Port :=
MySQL.User :=
MySQL.Password :=
MySQL.Connect;
MySQL.Database :=
MySQL.ExecSQL('SET CHARSET cp1251');
|
|
04-10-2007 08:22сообщение от автора материала Sairex: кстати правда чутог пришлось подправить вообще-то хорошо бы указать места расположения ошибок.
А чуть ранее, до того как увидел ваше сообщение, я отправил обновление MySql. Так что если изменения существенные, то придётся ещё раз обновить, а если мелочь пузатая, то в комментариях им самое место. |
|
04-10-2007 06:25Молодец афтар-жжет. Компоненты удобные, кстати правда чутог пришлось подправить а так все куль!
|
|
27-08-2007 05:42 Спасибо удобные компоненты, а как мне реализовать доступ к mysql из других локальных машин? |
|
21-06-2007 21:15Спасибо за компонент, пока все понятно. Это то, что я уже давно искал, а сам не решался сделать.
Большой респект и уважуха. |
|
25-05-2007 06:17сообщение от автора материала Спасибо, теперь буду знать. До этого момента не было необходимости знать были ли найдены записи для update (ну т.е. заранее знал что обновляю), поэтому не обращал внимания. Сейчас понадобилось обновить nное кол-во записей, если нет - добавить, хотел положиться на AffectedRows. |
|
25-05-2007 03:25А число найденных записей и число затронутых записей может не совпадать?
Ну да, например при UPDATE который не меняет содержимое какой-то записи (что было, то и записали), в этом случае с CLIENT_FOUND_ROWS вернётся общее число проанализированных записей, а без число реально изменённых, то есть тех в которых изменилось значение хотя бы одного поля.
Видимо из-за непонимания этого вы и удивляетесь, что иногда возвращает кол-во, а иногда нет. Только, если не ошибаюсь, в какой-то из версий был баг в этом механизме. |
|
23-05-2007 23:58сообщение от автора материала А число найденных записей и число затронутых записей может не совпадать? Если можно, какой-нибудь примерчик.
А без этого флага, как уже сказал, в тестовом примере возвращает кол-во, а подобный же update в другой программе не возвращает... Может у кого-то по этому поводу будут советы? |
|
23-05-2007 12:38При включении этого флажка будет возвращаться несколько не то:
`CLIENT_FOUND_ROWS' Return the number of found (matched) rows,
not the number of affected rows. |
|
23-05-2007 07:44сообщение от автора материала Что бы функция AffectedRows возвращала количество записей затронутых коммандами "update", "delete", "insert" - найдите в юните MySqlClasses строку:
FConnection := mysql_real_connect(FMySQL, PChar(FHost), PChar(FUser),
PChar(FPassword), PChar(FDatabase), FPort, nil, 0); и замените 0(ноль) на 2(два). Иначе она иногда возвращает кол-во, а иногда нет. |
|
|
|