|
Вопрос # 1 873/ вопрос открыт / |
|
Здравствуйте! Помогите пожалусто . вопрос на самом деле (мне почему то кажеться) легкий....
Я использую БД Акцессовскую, делфи7. При обнавлении базы я должна обнавить существующие записи и добавить новые.
но вот сложность возникает при переходе к инсерту...
т.е. при обработке блока if происходит пошаговое сравнение данных ... и если табель <> табелю из БД ...то естественно возникает ошибка : вставка записи... т.к. табель - д/б уникальным
Приложение: Переключить в обычный режим-
-
- while not DataModule1.ADOQuery3.Eof do
- begin
-
- If (StrToInt(Edit8.Text)=DataModule1.ADOQuery3.Fields.Fields[1].AsInteger) then
- begin
- DataModule1.ADOQuery1.Close;
- DataModule1.ADOQuery1.SQL.Clear;
- DataModule1.ADOQuery1.SQL.Add('update sotrudniky set adress='+ QuotedStr(Edit11.Text)+',data_roz ='+
QuotedStr(Edit7.Text)+',fio=' + QuotedStr(Edit6.Text) + ',UNN='+
QuotedStr(Edit9.Text)+',data_vidachi='+ QuotedStr(Edit10.Text)+',vidan='+
QuotedStr(Edit12.Text)+',seria='+ QuotedStr(Edit13.Text)+',ctaz_v_ap='+ QuotedStr(Edit14.Text)+'
where tab_nam = '+DataModule1.ADOQuery3.Fields.Fields[1].AsString+'');
- DataModule1.ADOQuery1.ExecSQL;
- end
-
- else begin
- DataModule1.ADOQuery1.Close;
- DataModule1.ADOQuery1.SQL.Clear;
- DataModule1.ADOQuery1.SQL.Add('insert into sotrudniky
(adress,data_roz,fio,UNN,data_vidachi,vidan,seria,ctaz_v_ap,tab_nam) values('+
QuotedStr(Edit11.Text)+','+ QuotedStr(Edit7.Text)+',' + QuotedStr(Edit6.Text) + ','+
QuotedStr(Edit9.Text)+','+ QuotedStr(Edit10.Text)+','+ QuotedStr(Edit12.Text)+','+
QuotedStr(Edit13.Text)+','+ QuotedStr(Edit14.Text)+','+ QuotedStr(Edit8.Text)+')');//ctaz_v_ap='+
QuotedStr(Edit14.Text)+' where tab_nam = '+DataModule1.ADOQuery3.Fields.Fields[1].AsString+'');
- DataModule1.ADOQuery1.ExecSQL;
- end;
- DataModule1.ADOQuery3.Next;
- end;
 |
Вопрос задала: Танюшка (статус: Посетитель)
Вопрос отправлен: 4 сентября 2008, 11:27
Состояние вопроса: открыт, ответов: 2.
|
Ответ #1. Отвечает эксперт: Шичко Игорь
Здравствуйте, Танюшка!
У Вас небольшая ошибка. Прежде чем заносить новые данные надо проверить весь набор табелей и при отсутствии тогда заносить. код ниже.
А вообще для нахождения табеля лучше воспользоваться SQL запросом с номером табеля.
Типа: Select tab_nam from sotrudniky where tab_nam = QuotedStr(Edit8.Text)
Если количество записей > 0 то табель есть, а если = 0 то вставляем новую запись.
Если есть вопросы пишите.
Приложение: Переключить в обычный режим- var
-
-
- DataModule1.ADOQuery3.First;//
- priznak:= False;
- while not DataModule1.ADOQuery3.Eof do
- begin //
- If (StrToInt(Edit8.Text)=DataModule1.ADOQuery3.Fields.Fields[1].AsInteger) then
- begin
- DataModule1.ADOQuery1.Close;
- DataModule1.ADOQuery1.SQL.Clear;
- DataModule1.ADOQuery1.SQL.Add('update sotrudniky set adress='+
QuotedStr(Edit11.Text)+',data_roz ='+ QuotedStr(Edit7.Text)+',fio=' + QuotedStr(Edit6.Text) +
',UNN='+ QuotedStr(Edit9.Text)+',data_vidachi='+ QuotedStr(Edit10.Text)+',vidan='+
QuotedStr(Edit12.Text)+',seria='+ QuotedStr(Edit13.Text)+',ctaz_v_ap='+ QuotedStr(Edit14.Text)+'
where tab_nam = '+DataModule1.ADOQuery3.Fields.Fields[1].AsString+'');
- DataModule1.ADOQuery1.ExecSQL;
-
- end;
- DataModule1.ADOQuery3.Next;
- end;
- ///
-
- begin
- DataModule1.ADOQuery1.Close;
- DataModule1.ADOQuery1.SQL.Clear;
- DataModule1.ADOQuery1.SQL.Add('insert into
(adress,data_roz,fio,UNN,data_vidachi,vidan,seria,ctaz_v_ap,tab_nam) values('+
QuotedStr(Edit11.Text)+','+ QuotedStr(Edit7.Text)+',' + QuotedStr(Edit6.Text) + ','+
QuotedStr(Edit9.Text)+','+ QuotedStr(Edit10.Text)+','+ QuotedStr(Edit12.Text)+','+
QuotedStr(Edit13.Text)+','+ QuotedStr(Edit14.Text)+','+ QuotedStr(Edit8.Text)+')');
- DataModule1.ADOQuery1.ExecSQL;
- end;
-
 |
Ответ отправил: Шичко Игорь (статус: 9-ый класс)
Время отправки: 4 сентября 2008, 12:10
Оценка за ответ: 5
|
Ответ #2. Отвечает эксперт: ANBsoft
Здравствуйте, Танюшка!
По логике, все совсем не так.
Смотрите приложение.
Примерно так, далее разберетесь.
Приложение: Переключить в обычный режим-
-
-
- //If (StrToInt(Edit8.Text)=DataModule1.ADOQuery3.Fields.Fields[1].AsInteger) then begin
-
- DataModule1.ADOQuery1.Close;
- DataModule1.ADOQuery1.SQL.Clear;
-
- DataModule1.ADOQuery1.ExecSQL;
- end
-
- else begin
- DataModule1.ADOQuery1.Close;
- DataModule1.ADOQuery1.SQL.Clear;
- DataModule1.ADOQuery1.SQL.Add('insert into sotrudniky
(adress,data_roz,fio,UNN,data_vidachi,vidan,seria,ctaz_v_ap,tab_nam) values('+
QuotedStr(Edit11.Text)+','+ QuotedStr(Edit7.Text)+',' + QuotedStr(Edit6.Text) + ','+
QuotedStr(Edit9.Text)+','+ QuotedStr(Edit10.Text)+','+ QuotedStr(Edit12.Text)+','+
QuotedStr(Edit13.Text)+','+ QuotedStr(Edit14.Text)+','+ QuotedStr(Edit8.Text)+')');//ctaz_v_ap='+
QuotedStr(Edit14.Text)+' where tab_nam = '+DataModule1.ADOQuery3.Fields.Fields[1].AsString+'');
- DataModule1.ADOQuery1.ExecSQL;
- end;
- //DataModule1.ADOQuery3.Next;
- // end;
 |
Ответ отправил: ANBsoft (статус: Студент)
Время отправки: 4 сентября 2008, 12:10
Оценка за ответ: 4
|
Мини-форум вопроса
Всего сообщений: 20; последнее сообщение — 4 сентября 2008, 23:19; участников в обсуждении: 4.
|
ANBsoft (статус: Студент), 4 сентября 2008, 12:22 [#1]:
По логике у Вас нет двух сотрудников с одинаковым табельным номером. Соответственно если Locate нашел табельный номер, то можно его редактировать, иначе - вставлять.
Сам с ADO не работал (больше FireBird привлекает), но может быть будет проще нормально настроить компоненты и использовать обычный Insert/Edit - Post чем такие глобальные Update и Insert?
|
|
Танюшка (статус: Посетитель), 4 сентября 2008, 12:36 [#2]:
DataModule1.Query.Close;
DataModule1.Query.sql.Clear;
DataModule1.Query.sql.Add('select tab_nam from sotrudniky where tab_nam ='+QuotedStr(Edit8.Text)+');
DataModule1.Query.Open;
выскакивает ошибка: несоотв. типов в условии отбора ....
как можно ее обойти????
|
|
ANBsoft (статус: Студент), 4 сентября 2008, 13:18 [#3]:
Я же написал про кавычки, попробуйте так:
DataModule1.Query.sql.Add('select tab_nam from sotrudniky where tab_nam ='''+QuotedStr(Edit8.Text)+''');
|
|
Шичко Игорь (статус: 9-ый класс), 4 сентября 2008, 13:19 [#4]:
Так как tab_nam это числовое значение (насколько я понял) поэтому и запрос нужно писать для числового значения
DataModule1.Query.sql.Add('select tab_nam from sotrudniky where tab_nam =' + Edit8.Text);
Только перед этим необходимо проверять точно ли числовое значение в Edit8.Text.
Кстати в запросе на вставку записи нужно подкорректировать под числовое значение.
|
|
ANBsoft (статус: Студент), 4 сентября 2008, 13:19 [#5]:
Это при условии что tab_nam - текстовое
|
|
Вадим К (статус: Академик), 4 сентября 2008, 13:25 [#6]:
to Бубырь Александр Николаевич
стоп-стоп. tab_nam это число или строка? Конструкция
'''+QuotedStr(Edit8.Text)+'''
сделает чистый ужас в результируей строке.
На сколько я вижу, там кавычки не нужны и QuotedStr также.
to Танюшка
Менять с помощью insert автоинкрементное поле нельзя. Может в этом вся загвоздка?
Галочка "подтверждения прочтения" - вселенское зло.
|
|
ANBsoft (статус: Студент), 4 сентября 2008, 13:41 [#7]:
Согласен, протормозил.
Сам никогда не пользовался QuotedStr, проще было писать '''.
|
|
Вадим К (статус: Академик), 4 сентября 2008, 13:54 [#8]:
и ещё раз замечание.
QuotedStr - хорошая функция. Но она для строк. Ведь представьте себе, что в запросе выглядит так
+'bla-bla="'+s+'"';
и переменная s попадает с внешнего мира, например напрямую с Edit. Всё вроде хорошо, пока кто то не додумается написать там что то вида
test"; drop table xxx; ---
Синтаксис будет конечно меняться от языка к языку, но идея думаю понятна.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
ANBsoft (статус: Студент), 4 сентября 2008, 14:47 [#9]:
Интересная мысль, за 10 лет ниразу не сталкивался с таким.
Хотя вредителя, который такое сможет написать QuotedStr, думаю, не остановит. А вообще, спасибо, буду иметь в виду.
|
|
Вадим К (статус: Академик), 4 сентября 2008, 14:54 [#10]:
Это не "интересная мысль", а реальная технология, с помощью которой падают сервера в интернете. QuotedStr таких остановит, так как он не только берёт в кавычки, а и экранирует лишние кавычки. А в базу они попадают так как надо - там лишних кавычек уже не будет.
Правда есть ещё десяток путей для вредительства.
есть такое правило " не доверяй входным данным, даже если они полученны от тебя и подписаны хорошим crc"
Галочка "подтверждения прочтения" - вселенское зло.
|
|
ANBsoft (статус: Студент), 4 сентября 2008, 15:26 [#11]:
Я для решения подобных проблем использовал свою функцию:
Function CheckName(s:String):String;
Var ss:String;
f:Integer;
Begin
//Ограничение на значения ячеек при импорте в Excel
ss:=s;
while (Length(ss)>0) and (ss[1] in ['=','-','+']) do Delete(ss,1,1);
//Ограничение на значения имен в SQL операторе
f:=1;
while (f<=Length(ss)) do
if ss[f] in [''''{,'*','/','=','-','+'}] then Delete(ss,f,1) //Часть ограничений потом снял
else Inc(f);
Result:=ss;
End;
|
|
Вадим К (статус: Академик), 4 сентября 2008, 15:39 [#12]:
за код - натянутая троечка. Мло того, что медленный код будет, так ещё ужас некрасивый (его можно переписать как минимум на пару строк короче.
При длине строки в 30-40 символов, уже будет давать заметные тормоза.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
ANBsoft (статус: Студент), 4 сентября 2008, 17:15 [#13]:
Не буду спорить, для меня это не актуально. Если бы эта функция вызывалась хотябы тысячами раз, стоило б париться, а так как написал давным давно, потом только вызывал.
На заре компьютеров все бились ради экономии каждого байта, сейчас время программистов стоит дороже мощностей компьютеров.
Я не призываю писать тормознутые, кривые программы, просто есть вещи которые стоит оптимизировать и вылизывать (тратить на это свое время), а есть те, которые работают правильно!, и это главное.
|
|
Вадим К (статус: Академик), 4 сентября 2008, 17:39 [#14]:
Вы случайно в разработке Висты не участвовали? там точно такая же идеолония. Я не призываю к преждевременной оптимизации - я призываю писать красивый код.
Вот к примеру в Вашем коде есть присваивание ss:=s; - без него всё будет работать, даже быстрее, и это не оптимизация, это просто нормальное написание кода.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
ANBsoft (статус: Студент), 4 сентября 2008, 18:00 [#15]:
В разработке Висты не участвовал, но при всех нареканиях на MicroSoft, это самая успешная софтверная компания (в финансовом плане), а это повод задуматься.
Как по мне, так красота кода стоит после надежности и скорости написания.
По поводу присваивания ss:=s, это просто привычка работать с локальными переменными. Да, передаваемое значение s и так локальное, а функция простая, но возможен вариант, что функция будет на несколько сотен строк, и в какой-то момент разработки появится необходимость объявить Var S (переменная перестанет быть локальной), прийдется полностью переделывать весь код функции.
Есть хорошее выражение, с которым я согласен:
"Клиенту лучше неоптимальная, большая, медленная, некрасивая программа, но работающая сейчас, чем маленькая, быстрая удобная, но которая будет через год".
Будет необходимость (и финансирование), всегда можно доработать и улучшить, а с вылизыванием мелочей часто теряешь клиента.
P.S. Нет предела совершенству, а лучшее - враг хорошего.
|
|
ANBsoft (статус: Студент), 4 сентября 2008, 18:13 [#16]:
Еще, может ошибаюсь, но все ускорение выльется в несколько тактов процессора на выполнение ss:=s; (увеличится счетчик использования для этой строки) и немного лишней памяти на хранение S до конца программы (так бы память освободилась после первого же while).
|
|
Вадим К (статус: Академик), 4 сентября 2008, 18:36 [#17]:
ещё раз повторю
я не говорю о вылизывании и оптимизации. Есть такая специальность "индус-кодер" (к национальности не имеет отношения - "индус" - от слова "индустриальный"). Так вот, таким ребятам платят за строки кода. Чем больше строк, тем лучше.
К тому же сами себе противоречите. Вы говорите, что не надо думать об оптимизации, а сами заведомо заводите переменную, что бы поменяв тип параметра на var, не иметь проблем.
Вообще то принято, что функции за редким исключением меняют входные параметры, поэтому у нормального программиста даже не возникает мысли о таком.
Мне на работе за подобный код просто сразу руки отрывают. Нет, я не оптимизирую, но если можно написать 3 строки, а я пишу 10, то это плохо, очень плохо. Даже если эти 10 работают быстрее. Только в редких случаях надо пойти на это.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
ANBsoft (статус: Студент), 4 сентября 2008, 19:22 [#18]:
Все зависит от требований, требуют от Вас писать кратко - куда ж деваться. Я работаю на себя, и как по мне, если 10 строк работают быстрее чем 3 красивых - я напишу 10. При работе с однокристалками (на уровне ASM или опциями компилятора) нужно выбирать что важнее размер кода, занимаемая память или скорость выполнения. Делфи в отличие от Си не предлагает таких опций в компиляторе, к тому же компилятор может сам свернуть лишнее и в вышеописанном коде скорее всего сам сразу освободит s, так как она более не используется (это видно при пошаговой трассировке алгоритма - variable inaccessible here due to optimization).
Повторюсь, все зависит от поставленных задач:
Вам платят деньги на работе, но требуют определенный вид кода,
мне платят деньги клиенты и требуют скорость реализации задачи и надежность работы, а код в исходниках вообще никто не увидит.
|
|
ANBsoft (статус: Студент), 4 сентября 2008, 19:28 [#19]:
----К тому же сами себе противоречите. Вы говорите, что не надо думать об оптимизации, а сами заведомо заводите переменную, что бы поменяв тип параметра на var, не иметь проблем.
В чем противоречие, я писал что мне важна надежность кода и скорость разработки, для этого и введена переменная, чтобы при дальнейших модернизациях функции максимально уменьшить переделки и убрать вероятность ошибки при пропуске одной из переменных при подобной переделке. Я написал, это привычка, выработанная через грабли, на которые наступал когда-то (опыт - сын ошибок трудных).
|
|
Вадим К (статус: Академик), 4 сентября 2008, 23:19 [#20]:
ой. не буду больше учить. через пару лет наткнётесь на какую то примитивную ошибку и будете мучиться. А всё потому, что делали как Вы хотели.
Красивый код пишеться быстрее и в последствии понимается быстрее что ещё важнее.
"код в исходниках вообще никто не увидит". Увидит. Вы. когда надо будет через полгода доделать немного. И на то, на что у меня уходит пара минут, у Вас может уйти недели дебагинга. Хотя ...
Галочка "подтверждения прочтения" - вселенское зло.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|