Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

MyDC.ru _ Программирование на Lua _ Вопросы Разработчикам Скриптов с SQL

Автор: Wariner 1.10.2008, 16:46

Вот есть

CODE
function UserConnected(sUser)
local ip = sUser.sIP
for row in db:rows("SELECT * FROM UserStat") do
if row.IP ~= IP then
local stmt=db:prepare("SELECT * FROM UserStat")
if stmt then
db:exec("INSERT INTO UserStat (Nick,IP) VALUES ('"..sUser.sNick.."', '"..sUser.sIP.."')")
end
end
end
Core.SendToNick(sUser.sNick,"$UserCommand 1 3 Статистика$<%[mynick]> !ui %[line:Введите ник]|")
end

возникла небольшая проблема... код выполняется если в базе записан хотябы один юзер а если она пустая то глухо... Как это решить?

Автор: Setuper 1.10.2008, 16:57

1). Ты понимаешь, что ты пишет? Если понимаешь, то объясни. Потому что, если даже таблица не пустая, данный код (если исправить локальную переменную ip на IP) создаст гигантское количество повторяющихся записей.

2). Какую нагрузку несёт буква s в начале переменной sUser? Вроде как попытка использовать венгерскую нотацию, но все же не понятно почему таблица обозначается как строка? s - от слова String. По венгерской нотации надо бы писать tUser. t - Table.

3). Я полагаю, что ты хочешь написать что-то в этом роде:

Код
function UserConnected(tUser)
    local stmt=db:prepare("SELECT IP FROM UserStat WHERE IP='"..tUser.sIP.."'")
    if not stmt or not stmt:first_row() then
        db:exec("INSERT INTO UserStat (Nick,IP) VALUES ('"..tUser.sNick.."', '"..tUser.sIP.."')")
    else
        db:exec("UPDATE UserStat SET Nick='"..tUser.sNick.."' WHERE IP='"..tUser.sIP.."'")
    end
    Core.SendToUser(tUser,"$UserCommand 1 3 Статистика$<%[mynick]> !ui %[line:Введите ник]&#*124;")
end
* - удалить.

Заметь я справил в коде sUser на tUser, следуя венгерской нотации.

Если не понятно, что делается в коде, - спрашивай, я объясню подробно))

Автор: Wariner 1.10.2008, 17:18

скорее нет чем да))) но вот этот код

CODE
function UserConnected(sUser)
local stmt=db:prepare("SELECT * FROM UserStat")
if stmt then
db:exec("INSERT INTO UserStat (Nick,IP) VALUES ('"..sUser.sNick.."', '"..sUser.sIP.."')")
end
Core.SendToNick(sUser.sNick,"$UserCommand 1 3 Статистика$<%[mynick]> !ui %[line:Введите ник]|")
end


записывает в базу мой ник и мой ип при коннекте(ну или другого юзера)

Автор: Setuper 1.10.2008, 17:33

Смотри пост выше. Если не понятно что-то, я ещё раз подробно объясню, что в каждой строчке делается)))))

Автор: Wariner 1.10.2008, 17:45

Цитата(Setuper @ 1.10.2008, 17:57) *
2). Какую нагрузку несёт буква s в начале переменной sUser? Вроде как попытка использовать венгерскую нотацию, но все же не понятно почему таблица обозначается как строка? s - от слова String. По венгерской нотации надо бы писать tUser. t - Table.

никакого смысла она не несёт если напишешь что то про нотацию будет хорошо)))
Цитата(Setuper @ 1.10.2008, 17:57) *
3). Я полагаю, что ты хочешь написать что-то в этом роде:

Я хочу написать что то типо юзер инфо написаного Николя только наверно более сжато. А от данного куска кода хочу чтобы при входе на хаб он смотрел нет ли IP юзера в базе и если нет заприсывал его туда со всеми остальными данными как ник и т.д.
Цитата(Setuper @ 1.10.2008, 17:57) *
Код
function UserConnected(tUser)
    local stmt=db:prepare("SELECT IP FROM UserStat WHERE IP='"..tUser.sIP.."'")
    if not stmt or not stmt:first_row() then
        db:exec("INSERT INTO UserStat (Nick,IP) VALUES ('"..tUser.sNick.."', '"..tUser.sIP.."')")  -- вставляет в базу кик и ип
    else
        db:exec("UPDATE UserStat SET Nick='"..tUser.sNick.."' WHERE IP='"..tUser.sIP.."'") -- меняет ник на новый у юзера с данным ip
    end
    Core.SendToUser(tUser,"$UserCommand 1 3 Статистика$<%[mynick]> !ui %[line:Введите ник]&#*124;")
end
* - удалить.

Буду очень признателен если распишешь поподробнее)))

Автор: Setuper 1.10.2008, 18:17

Код
function UserConnected(tUser)

    --[[Выполнение предзапроса.
    Для экономии процессорного времени и памяти вместо запроса SELECT *,
    используем запрос SELECT IP, но по сути можно и так, и так.
    Запрос SELECT IP FROM UserStat выдаст все ip адреса,
    но зачем нам все адреса, когда нам нужен ip адрес вошедшего юзера.
    поэтому пишем запрос и добавляем, что поле IP в нашей таблице должно равняться tUser.sIP.]]

    local stmt=db:prepare("SELECT IP FROM UserStat WHERE IP='"..tUser.sIP.."'")


    --[[Проверка, что предзапрос не выполнился или нет ни одной строки нашего запроса.
    В принципе можно было написать просто if not stmt then]]

    if not stmt or not stmt:first_row() then


        --[[Если наш запрос на выдачу ip адреса пользователя не прошёл,
        то это означает, что пользователя с таким ip нету в нашей базе.
        Значит надо его туда добавить.
        Запрос INSERT INTO 'имя_таблицы' ('столбцы') VALUES ('вносимые_данные')
        заносит данные в таблицу]]

        db:exec("INSERT INTO UserStat (Nick,IP) VALUES ('"..tUser.sNick.."', '"..tUser.sIP.."')")
    else


        --[[Если наш запрос на получение из базы данных ip адреса вошедшего юзера выполнился,
        то нам не надо вносить данные в базу данных.
        Если попытаться внести данные запросом INSERT, то данные занесутся
        и будут две одинаковые строки в таблице, что нарушит целостность базы данных.
        Однако нужно учесть, что юзер может зайти с другого ника,
        поэтому надо обновить ник пользователя.
        Запрос, осуществляющий обновление уже существующих данных в таблице выглядит так:
        UPDATE 'имя_таблицы' SET 'обновляемое_поле'='новое_значение']]

        db:exec("UPDATE UserStat SET Nick='"..tUser.sNick.."' WHERE IP='"..tUser.sIP.."'")
    end
    Core.SendToUser(tUser,"$UserCommand 1 3 Статистика$<%[mynick]> !ui %[line:Введите ник]&#*124;")
end


Надеюсь понятно объяснил big_smile.gif

Автор: Wariner 1.10.2008, 18:26

Супер)))) Думаю понятнее просто некуда)))) БД это вещь))))
А ещё вопрос если бы можно было открыть БД с помощью какого нибудь визуального редактора она была бы вот такой:
id................Nick.................IP
1............-=Wariner=-......10.2.........
2................ник2................ip2
и тд.(без точек конечно же) Или я ошибаюсь?

Автор: Setuper 1.10.2008, 18:30

ты прав на все 100

Автор: Wariner 1.10.2008, 19:12

блин, ну что ж у меня затыки на каждом шагу(((
вот

CODE
function UserConnected(sUser)
Core.GetUserAllData(sUser)
local shara = sUser.iShareSize or 0
Core.SendToUser(sUser, GetNormalShare(shara))
local stmt=db:prepare("SELECT IP FROM UserStat WHERE IP='"..sUser.sIP.."'")
if not stmt or not stmt:first_row() then
db:exec("INSERT INTO UserStat (Nick,IP,Shara) VALUES ('"..sUser.sNick.."', '"..sUser.sIP.."', '"..shara.."')")
else
db:exec("UPDATE UserStat SET Nick='"..sUser.sNick.."', Shara='"..shara.."' WHERE IP='"..sUser.sIP.."'")
end
Core.SendToNick(sUser.sNick,"$UserCommand 1 3 Статистика$<%[mynick]> !ui %[line:Введите ник]|")
end

с ником и ипом всё нормально, а с шарой начались проблемы(((
Добавил при конекте отсылание в чат шары для проверки там всё норм, после записи в БД и извлечении с шарой происходят непонятки((( например с одного клиента шара 17.69ГБ а показыват 1.694 ГБ а с другого 18 ГБ а показывает минус и большое число байтов(дело не в функции GetNormalShare это я проверил)

Автор: Setuper 1.10.2008, 19:28

Как ты создаёшь таблицу напиши

Автор: Wariner 1.10.2008, 19:44

CODE
function OnStartup()
db = sqlite3.open("Userstat.db3")
db:exec("CREATE TABLE UserStat (id INTEGER PRIMARY KEY, Nick INTEGER, IP INTEGER, Shara INTEGER)")
end

Не ужели у шары тип данных не INTEGER beat_brick.gif

Автор: Setuper 1.10.2008, 21:15

Код
db:exec("CREATE TABLE UserStat (id INTEGER PRIMARY KEY, Nick TEXT, IP TEXT, Shara TEXT)")

Автор: Wariner 1.10.2008, 21:44

2Setuper: А есть такая прога которая бы открывала БД как блокнот? чтобы наглядгно видеть что получилось? Если есть подскажи название, пожалуйста.

Автор: Setuper 1.10.2008, 21:55

http://mydc.ru/r/?http://sqlitebrowser.sourceforge.net/

Вообще говоря это можно найти http://mydc.ru/topic70.html?view=findpost&p=228
Просто иногда достаточно повнимательнее читать посты. Внизу первого поста я приводил наиболее полезные линки для работы с SQLite. big_smile.gif

Автор: Wariner 2.10.2008, 17:52

А можно ли создавать столбцы в базе по ходу дела? Т.е. при заходе на хаб идёт сличение IP если IP в БД есть то сличается ник, если он отличается от от записанного в БД то создаётся новый столбец типо "старый ник1" и туда перемещается ник из БД а новый Заносится на место старого.

Автор: Setuper 2.10.2008, 20:14

Код
db:exec("ALTER TABLE имя_таблицы ADD имя_столбца")


Опять же по указанным мною ссылкам это легко находится:
http://mydc.ru/r/?http://sb-news.net/sqlite.php?page=35

Автор: Wariner 2.10.2008, 21:38

с помощью sqlitebrowser`а обнаружелась ошибка в коде

CODE
function UserConnected(sUser)
Core.GetUserAllData(sUser)
local shara = sUser.iShareSize or 0
local stmt=db:prepare("SELECT IP FROM UserStat WHERE IP='"..sUser.sIP.."'")
if not stmt or not stmt:first_row() then
db:exec("INSERT INTO UserStat (Nick,IP,Shara,Msg,DataOff) VALUES ('"..sUser.sNick.."', '"..sUser.sIP.."', '"..shara.."', '0', '0')")
else
db:exec("UPDATE UserStat SET Nick='"..sUser.sNick.."', Shara='"..shara.."' WHERE IP='"..sUser.sIP.."'")
end
Core.SendToNick(sUser.sNick,"$UserCommand 1 3 Статистика$<%[mynick]> !ui %[line:Введите ник]|")
end

С первым вошедшим всё нормально. При заходе второго человека он сразу же приступает к выполнению условия else. Я честно говоря не понимаю почему так.
2Setuper ещё раз перечитал твоё описание вроде поо нему всё верно...
Цитата
--[[Проверка, что предзапрос не выполнился или нет ни одной строки нашего запроса.
В принципе можно было написать просто if not stmt then]]

если делаю просто то вообще в БД ничего не записывается даже у первого юзера(((

Автор: Setuper 2.10.2008, 22:57

Итак, по порядку:

Цитата(Wariner @ 2.10.2008, 22:38) *
С первым вошедшим всё нормально. При заходе второго человека он сразу же приступает к выполнению условия else. Я честно говоря не понимаю почему так.
2Setuper ещё раз перечитал твоё описание вроде поо нему всё верно...


Это не единственный глюк dll библиотеки базы данных для API2.
Глюки:
1). Нельзя создать более одной таблицы в базе данных.
2). Нельзя создать более одной записи в таблице.

Данные глюки отсутствуют в полноценной библиотеке для API1.
Именно по этой причине у меня в подписи написано:
PtokaX 0.3.6.0 + Lua 5.1.3 + SQLite 3.2.7 + SBot 6.0RC3 - now
PtokaX 0.4.1.1 + Lua 5.1.3 + SQLite 3.5.6 + SBot 7.0RC1 - in the future!
still_dreaming.gif


Цитата(Wariner @ 2.10.2008, 22:38) *
если делаю просто то вообще в БД ничего не записывается даже у первого юзера(((

Что касается этого, то это я не верно написал. Извиняюсь.
Дело в том, что предзапросы должны как-то обрабатываться обращением к базе данных. В случае, если написать просто if not stmt then, то обработки этого предзапроса не произошло. Обрабатывать предзапрос следует одним из из следующих способов:
Код
stmt:first_row()
stmt:rows()
stmt:cols()
stmt:exec()


Поэтому правильно писать так:
Код
if not stmt or not stmt:first_row() then


Способ обработки предзапроса stmt:first_row() выбран из-за экономии процессорного времени и памяти - это самый эффективный запрос для проверки.


Поэтому как ни крути а на новой PtokaX ты не сможешь ничего нормально реализовать, используя БД.
Проблема с DLL библиотекой уже давно остро стоит!

Автор: Wariner 3.10.2008, 8:23

т.е

id................Nick.................IP
1............-=Wariner=-......10.2.........
2 - а вот эту строку записать уже не возможно? я правильно понял?:'-(

а ещё хочу уточнить проблема только в dll или и в sqlite3.lua тоже?
PS: а не известно когда сие чудо сделают рабочим?
PS2: что то я с утра натупил.... Ведь коогда не было проверки на новый или старый IP в базу сохранялось несколько строк!!!
PS3: совсем запутался(((

Автор: Setuper 3.10.2008, 10:50

Ага. В общем тухлая библиотека и как она работает диву даёшься.
Ещё раз говорю переходи на API1 там таких проблем нет.

Я пытался скомпилить нормальную либу, но запутался в def файлах и скомпилив она у меня не работала.
Хотя я думаю, что если разобраться, то скомпилить можно, вот только нет времени разбираться.

Автор: Wariner 26.2.2009, 16:47

в чём здесь ошибка? точнее почему если написать заданную строку "ыыыыы" вместо sRusMsg запись в БД производится в противном случае нет?

Код
function OnError(sMsg)
    local sRusMsg = ""
    local tRusError = {
        ["bad argument"] = "плохой аргумент",
        ["string expected"] = "ожидается строка",
    }
    for i,v in pairs(tRusError) do
        sRusMsg = string.gsub(sMsg, i, v)
    end
    Core.SendToAll(sRusMsg)
    db:exec("CREATE TABLE le"..os.date("%d%m%Y").." (id INTEGER PRIMARY KEY, Time TEXT, Error TEXT)")
    db:exec("INSERT INTO le"..os.date("%d%m%Y").." (Time,Error) VALUES ('"..os.date("%H:%M:%S").."', '"..sRusMsg.."')")
end


и это не пашет
Код
function CheckBans(tUser)
    if tUsers[tUser.sIP].Ban then
        if tUsers[tUser.sIP].Ban.Time == "full" then
            Core.SendToUser(tUser, "<"..sBot.."> \r\n\r\n\t\t\tВы навсегда забанены на этом хабе \r\n\t\t\tПо причине: "..tUsers[tUser.sIP].Ban.Reason.."\r\n\t\t\tНаказал:"..tUsers[tUser.sIP].Ban.Punished.."\r\n")
            db:exec("CREATE TABLE ldu"..os.date("%d%m%Y").." (id INTEGER PRIMARY KEY, Time TEXT, Nick TEXT, IP TEXT, Reason TEXT)")
            db:exec("INSERT INTO ldu"..os.date("%d%m%Y").." (Time,Nick,IP,Msg) VALUES ('"..os.date("%H:%M:%S").."', '"..tUser.sNick.."', '"..tUser.sIP.."', 'Навсегда забанен')")            
            Core.Disconnect(tUser)



а вот это работает
Код
    if tCfg.MainLogs == 1 then
        local _,_,sData = string.find(sData, "%b<>%s+(.*)")
        db:exec("CREATE TABLE lmc"..os.date("%d%m%Y").." (id INTEGER PRIMARY KEY, Time TEXT, Nick TEXT, IP TEXT, Msg TEXT)")
        db:exec("INSERT INTO lmc"..os.date("%d%m%Y").." (Time,Nick,IP,Msg) VALUES ('"..os.date("%H:%M:%S").."', '"..tUser.sNick.."', '"..tUser.sIP.."', '"..sData.."')")
    end

Автор: Setuper 26.2.2009, 17:33

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

Автор: Wariner 26.2.2009, 19:05

с фуенкцией эроров разобрался а вот со второй нет((( какие могут влиять символы и чем их экранировать?

Автор: Setuper 27.2.2009, 0:36

Ну и в чём была причина?
Вторая функция по идее тоже должна пахать.

Автор: Wariner 27.2.2009, 18:55

в эррорах действительно была одинарная кавычка, а во второй просто моя невнимательность... beat_brick.gif

Автор: Wariner 28.2.2009, 23:00

Что то со скулайтом у меня проблемы на каждом шагу. Теперь не работает апдейт таблицы. вроде внимательно посмотрел как было аписанно в середине этой темы, но не пашет(((

Код
function UserDisconnected(tUser)
    db:exec("UPDATE Users SET Offdate='"..os.date("%d.%m.%Y в %H:%M").."' WHERE IP='"..tUser.sIP.."'")
end


таблица такая:
Код
    db:exec("CREATE TABLE Users (id INTEGER PRIMARY KEY, Nick TEXT, IP TEXT, Shara NUMERIC, Msg NUMERIC, Time NUMERIC, Enterdate TEXT, Offdate TEXT, Bantime TEXT, Banreason TEXT,"..
    "Banpunished TEXT, Gagtime TEXT, Gagreason TEXT, Gagpunished TEXT, Gagtype TEXT, Downloadtime TEXT, Downloadreason TEXT, Downloadpunished TEXT, Seachtime TEXT, Seachreason TEXT,"..
    "Seachpunished TEXT)")


и ещё можно ли инсертить в столбцы таблицы по отдельности?

Автор: Setuper 1.3.2009, 1:41

Условие должно проверяться по уникальному столбцу. Столбец IP не является у тебя уникальным. Уникальным столбцом у тебя является первичный ключ, то есть id. Поэтому в твоём случае есть 2 варианта:

либо писать так:

Код
"UPDATE Users SET Offdate='"..os.date("%d.%m.%Y в %H:%M").."' WHERE id='"..id.."'"

либо делать столбец ip адреса уникальным:
Код
"CREATE TABLE Users (id INTEGER PRIMARY KEY, Nick TEXT, IP TEXT UNIQUE, ...

Автор: Wariner 2.3.2009, 15:56

Цитата(Setuper @ 1.3.2009, 1:41) *
либо делать столбец ip адреса уникальным:
Код
"CREATE TABLE Users (id INTEGER PRIMARY KEY, Nick TEXT, IP TEXT UNIQUE, ...

это не помогло(((
Код
    db:exec("CREATE TABLE Users (id INTEGER PRIMARY KEY, Nick TEXT, IP TEXT UNIQUE, Shara NUMERIC, Msg NUMERIC, Time NUMERIC, Enterdate TEXT, Offdate TEXT, Bantime TEXT, Banreason TEXT,"..
    "Banpunished TEXT, Gagtime TEXT, Gagreason TEXT, Gagpunished TEXT, Gagtype TEXT, Downloadtime TEXT, Downloadreason TEXT, Downloadpunished TEXT, Seachtime TEXT, Seachreason TEXT,"..
    "Seachpunished TEXT)")


может в синтаксисе где ошибка, так как поле ип не стало уникальным? с id работает но лучшеб чтоб сразу по ип определяло

Автор: Setuper 2.3.2009, 16:42

Да... что-то по-прежнему библиотека работает неправильно!

Автор: Wariner 2.3.2009, 16:50

ты сам проверил или делаешь выводы на основании моих постов? Если второе то лучше проверь я мог накасячить.

Автор: Setuper 2.3.2009, 16:56

Сам я не использую пока новую версию библиотеки.

Проверив работу либы, можно заключить, что работать с такой библиотекой невозможно!

Команда CREATE и INSERT работают правильно
Не работают команды DROP и UPDATE

Поэтому по-прежнему единственно рабочая библиотека - это библиотека под API 1.

Автор: Wariner 2.3.2009, 17:51

не ну если по id то то апдейт работает. гемор конечно но всё же. можно ли апдейтить сразу несколько позиций?

Автор: Setuper 2.3.2009, 17:58

Частичная работа каких-то команд - это не выход.

Если мне удастся скомпилить хотя бы одну простейшую либу, то я покапаюсь и посмотрю в чем может быть причина. При удачном стечении обстоятельств возможно даже скомпилю с исходниками более свежей версии sqlite 3.6.1

Автор: Wariner 2.3.2009, 19:42

возможно не выход, но основу то наверно написать можно.

PS: надеюсь рабочая либа будет скоро))))

Setuper, как бы ты посоветовал сделать топ сообщений на основе бд? Всё таки отправлять запрос к базе при каждом сообщении наверно не оптимизировано

Автор: alex82 2.3.2009, 20:04

Setuper

Возможно, я накосячил при переносе исходников в C++ Builder. Если мне таки удастся найти работоспособный Visual C++, то попробую собрать им.

Автор: Setuper 2.3.2009, 21:35

Скомпилил новую версию либы 3.6.11
Сейчас протестирую и выложу. По первым тестам вроде всё работает.

Автор: Wariner 3.3.2009, 18:47

ждёмс......

меня щас разорвёт от ожидания xDDDDDDDDDDDDD

Автор: Setuper 3.3.2009, 20:07

К сожалению по-прежнему получается левая либа, не создающая более 1 таблицы(((

Автор: Wariner 3.3.2009, 20:24

печально((( Значит буду пользовать либу от алекса.

2Setuper: подскажи как получить значение конкретной ячейки в таблице т.е есть

id nick ip msg
1 nik1 ip1 10
2 nik2 ip2 20
3 nik3 ip3 30

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

Автор: Setuper 3.3.2009, 21:48

Код
SELECT msg FROM table WHERE ip = 'ip2'

Автор: Wariner 3.3.2009, 21:58

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

Автор: Setuper 3.3.2009, 22:16

http://mydc.ru/ipb.html?s=&showtopic=70&view=findpost&p=1995

Код
local tMsg = DoFirstSelect("SELECT msg FROM table WHERE ip = 'ip2'")
Core.SendToAll(tostring(tMsg.ip))

Автор: alex82 3.3.2009, 22:43

Setuper

Можешь написать скриптик для тестирования проблемных запросов?

Автор: Setuper 3.3.2009, 23:36

Скрипт для тестирования SQLite:  test_sqlite.lua ( 1.66 килобайт ) : 3

Ниже приведены результаты тестов для мною собранной библиотеки:  PXSqlite3.rar ( 177.65 килобайт ) : 4

Код
Version sqlite: 3.6.11
CREATE TABLE test (id INTEGER PRIMARY KEY, content Text): true
CREATE TABLE test2 (id INTEGER PRIMARY KEY, content Text): true
INSERT INTO test (content) VALUES('value'): true
INSERT INTO test (content) VALUES('value2'): true
INSERT INTO test2 (content) VALUES('value'): false
SELECT * FROM test: true
SELECT * FROM test2: true
DROP TABLE test2: false
SELECT * FROM test2: false
UPDATE test SET content='val' WHERE id='1': true
SELECT content FROM test WHERE id='1': val

Автор: alex82 4.3.2009, 0:54

Код
[23:40:44] Version sqlite: 3.2.7
[23:40:44] CREATE TABLE test (id INTEGER PRIMARY KEY, content Text): true
[23:40:44] CREATE TABLE test2 (id INTEGER PRIMARY KEY, content Text): true
[23:40:44] INSERT INTO test (content) VALUES('value'): true
[23:40:44] INSERT INTO test (content) VALUES('value2'): true
[23:40:44] INSERT INTO test2 (content) VALUES('value'): true
[23:40:44] SELECT * FROM test: true
[23:40:44] SELECT * FROM test2: true
[23:40:44] DROP TABLE test2: true
[23:40:44] SELECT * FROM test2: false
[23:40:44] UPDATE test SET content='val' WHERE id='1': true
[23:40:44] SELECT content FROM test WHERE id='1': val


Странно, но DROP работает.

PS. Обьясни плиз блондинке(то бишь мнеbig_smile.gif), что делает функция CheckSelect.

Автор: Setuper 4.3.2009, 1:19

Функция CheckSelect проверяет возвращает ли запрос SELECT данные (возвращает true, если запрос возвращает данные и nil в противном случае).

Так то оно так, но вот попробуй вот такую проверку:

Код
function OnStartup()
  DoSql"CREATE TABLE test (id INTEGER PRIMARY KEY, content Text)"
  DoSql"CREATE TABLE test2 (id INTEGER PRIMARY KEY, content Text)"
  DoSql"DROP TABLE test2"
  DoSql"INSERT INTO test2 (content) VALUES('value')"
  db:close()
end


При правильной работе библиотеке результат должен быть следующим:
Код
CREATE TABLE test (id INTEGER PRIMARY KEY, content Text): true
CREATE TABLE test2 (id INTEGER PRIMARY KEY, content Text): true
DROP TABLE test2: true
INSERT INTO test2 (content) VALUES('value'): false


Я думаю, что у тебя не получится такого результата.

Для просмотра базы данных используй sqlite браузер:  SQLite_Database_Browser.rar ( 1.06 мегабайт ) : 5

Автор: alex82 4.3.2009, 1:34

Код
[00:29:29] CREATE TABLE test (id INTEGER PRIMARY KEY, content Text): true
[00:29:29] CREATE TABLE test2 (id INTEGER PRIMARY KEY, content Text): true
[00:29:29] DROP TABLE test2: true
[00:29:29] INSERT INTO test2 (content) VALUES('value'): false


Именно такой и получился.

Но при просмотре базы в браузере, таблица test2 присутствовала.

Автор: Setuper 4.3.2009, 2:02

Вот и я о том же.

Вообще какое-то странное поведение


Я немного неверно написал в функции CheckSelect. Надо так:

Код
local function CheckSelect(request, no)
    local stmt=db:prepare(request)
    if stmt and stmt:first_row() then
      if bDebug then
        Core.SendToAll(request..": "..tostring(not no))
      end
      return true
    end
    if bDebug then
      Core.SendToAll(request..": "..tostring(no or "false"))
    end
    return nil
end


Но просмотр через браузер говорит, что таблица не удаляется.

Код
  DoSql"CREATE TABLE test (id INTEGER PRIMARY KEY, content Text)"
  DoSql"CREATE TABLE test2 (id INTEGER PRIMARY KEY, content Text)"
  DoSql"DROP TABLE test2"
  CheckSelect"SELECT * FROM test2"
  DoSql"CREATE TABLE test2 (id INTEGER PRIMARY KEY, content Text)"
  DoSql"INSERT INTO test2 (content) VALUES('value')"
  CheckSelect"SELECT * FROM test2"


Результат:
Код
CREATE TABLE test (id INTEGER PRIMARY KEY, content Text): true
CREATE TABLE test2 (id INTEGER PRIMARY KEY, content Text): true
DROP TABLE test2: true
SELECT * FROM test2: false
CREATE TABLE test2 (id INTEGER PRIMARY KEY, content Text): true
INSERT INTO test2 (content) VALUES('value'): true
SELECT * FROM test2: false

Автор: alex82 4.3.2009, 13:26

Копнул либу чуть глубже.

Блин, такая же хрень, что и LuaSocket - большинство низкоуровневых функций написано на Lua.

Отпало всякое желание копаться дальше в этом гуане.

Переделал тестовый скрипт для вывода сообщений об ошибках вместо false.

Код
[12:13:53] DROP TABLE test2: database disk image is malformed
[12:13:53] INSERT INTO test2 (content) VALUES('value'): database disk image is malformed

Мдя...

Автор: Wariner 4.3.2009, 18:05

Цитата(Setuper @ 3.3.2009, 22:16) *
http://mydc.ru/ipb.html?s=&showtopic=70&view=findpost&p=1995
Код
local tMsg = DoFirstSelect("SELECT msg FROM table WHERE ip = 'ip2'")
Core.SendToAll(tostring(tMsg.ip))

я так понимаю должно быть:
Код
local tMsg = DoFirstSelect("SELECT msg FROM table WHERE ip = 'ip2'")
Core.SendToAll(tostring(tMsg.msg))


сколько цифр может хранить тип NUMERIC?
может конечно дело и не в этом. просто в SQL браузере я смотрю правильное количество шары, а скрипт выводит на порядок меньше
460995173 --выводит
34820733541 -- должно быть

Автор: Setuper 4.3.2009, 18:34

В sqlite числовые типы служат только для сортировки, поэтому числа можно хранить и в текстовых полях. То есть под шару следует ставить тип TEXT

Автор: Wariner 21.3.2009, 0:06

Есть вполне рабочий код:

Код
function OnStartup()
    require "luasql.mysql" -- подключаем библиотеку
    env = assert (luasql.mysql()) -- вызываем основную функцию из библиотеки
    con = assert (env:connect("test","root","пароль","localhost"))    -- соединяемся с базой данных
    res = assert (con:execute[[
        CREATE TABLE IF NOT EXISTS MsgTop(
        Nick varchar(50) NOT NULL PRIMARY KEY,
        Msg MEDIUMINT(10) NOT NULL
        )
    ]])
end

function OnExit()
    --cur:close()
    con:close()
    env:close()
end    

function ChatArrival(tUser, sData)
    local cur = assert(con:execute("SELECT Nick, Msg from MsgTop WHERE Nick = '"..tUser.sNick.."'"))
    row = cur:fetch ({}, "a")
    if not row then
        local res = assert(con:execute(string.format("INSERT INTO MsgTop VALUES ('%s', '%s')]], tUser.sNick, 1")))
    else
        local iMsg = row.Msg + 1
        local res = assert(con:execute("UPDATE MsgTop SET Msg = "..iMsg.." WHERE Nick = '"..tUser.sNick.."'"))    
    end
end


Обычный топ сообщений.

2Setuper: Что можно исправить в самом коде(корявости и т.д.) и как сделать сортировку? позволяет ли MySQL автоматически сортировать таблицу или как всегда ручками!

Автор: alex82 21.3.2009, 0:32

Код
      local iMsg = row.Msg + 1
        local res = assert(con:execute("UPDATE MsgTop SET Msg = "..iMsg.." WHERE Nick = '"..tUser.sNick.."'"))

А почему бы не сделать проще:
Код
assert(con:execute("UPDATE MsgTop SET Msg = Msg+1 WHERE Nick = '"..tUser.sNick.."'"))


А сортировка, если я не ошибаюсь, производится так:
Код
con:execute("SELECT Nick, Msg from MsgTop ORDER BY Msg")

Автор: Setuper 21.3.2009, 0:59

Сортировка:

Код
SELECT select_expression FROM table WHERE where_definition ORDER BY col_name [ASC | DESC]


Курсоры всегда нужно закрывать, если их используешь!!!


Код
require "luasql.mysql"
local env = assert(luasql.mysql())
local con = assert(env:connect("test","root","пароль","localhost"))

assert(con:execute[[
  CREATE TABLE IF NOT EXISTS `MsgTop`(
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `Nick` VARCHAR(64) NOT NULL,
    `Msg` MEDIUMINT(10) NOT NULL DEFAULT 0,
    PRIMARY KEY(`id`),
    UNIQUE(`Nick`)
  )
]])

function OnExit()
    con:close()
    env:close()
end    

function ChatArrival(tUser, sData)
  con:execute(("INSERT INTO `MsgTop` (`Nick`) VALUES ('%s')"):format(tUser.sNick))
  con:execute(("UPDATE `MsgTop` SET `Msg` = `Msg` + 1 WHERE `Nick` = '%s'"):format(tUser.sNick))
end

Автор: Wariner 21.3.2009, 11:25

Для чего нужен id? И ещё что нужно выделять апострофами а что нет? В доках по MySQL ничего конкретного вроде не нашёл....

upd: прошу ещё раз посмотреть всё ли норм написано))))) Есмли да то начну переделку некоторых своих скриптов))))

 MsgTopMySQL.lua ( 1.69 килобайт ) : 3
 

Автор: Setuper 21.3.2009, 12:34

id - это индексированное поле. Служит для наискорейшего выполнения запросов.

Апострофами выделяются имена полей, таблиц, баз данных и тд. Выделять апострофами не обязательно, если имя уникально (не используется в синтаксисе sql), однако хорошие программисты, дабы не отвлекаться на эту мелочь, всегда выделяют все имена апострофами. Приведу пример:

Код
assert(con:execute"CREATE TABLE IF NOT EXISTS TABLE(`field` INT)")
в данном случае запрос не выполнится и будет выдана ошибка, всё из-за того, что имя таблицы - TABLE, является ключевым словом sql. Однако если написать так:
Код
assert(con:execute"CREATE TABLE IF NOT EXISTS `TABLE`(`field` INT)")
то запрос выполнится. Поэтому чтобы не отвлекаться и не проверять на совпадение с ключевыми словами, имена всех придуманных объектов заключаем в апострофы.

По поводу скрипта:
1) Не закрыт курсор!!!!!
2) Ограничение можно делать в самом sql, используя LIMIT.

 MsgTopMySQL.lua ( 1.64 килобайт ) : 2

Автор: Wariner 22.3.2009, 0:10

Класс))))))))) вот токо я до сих пор не придумал таблицы((((

upd: как правильно сделать связь таблиц, где почитать? какой оператор?

Автор: Setuper 22.3.2009, 0:14

Ни в sqlite, ни в mysql нет полнеценной поддержки связей. Связи являются визуальными, но тем не менее они должны быть.

Автор: Wariner 22.3.2009, 0:21

ну а если поконкретнее немного? что должна содержать 3 таблица(которая для связи)?

Автор: Setuper 22.3.2009, 0:42

Смотря какой тип связи.

2 таблицы со связью многие-ко-многим связываются через третью таблицу.
в третьей таблице находятся ссылка на ключи из двух других

Автор: Wariner 22.3.2009, 0:47

т.е. получается есть таблицы

id....NIKC
1.....ник1
2.....ник2


id....IP
1.....ип1
2.....ип2

а третья будет вида
id.......id_NICK......id_IP
1.......id_ник1......id_ип1
2.......id_ник1......id_ип2

так?

Автор: Setuper 22.3.2009, 0:55

возможно, что будет так:

id....NIKC
1.....ник1
2.....ник2


id....IP
1.....ип1
2.....ип2

а третья будет вида
id.......id_NICK......id_IP
1.......id_ник1......id_ип1
2.......id_ник1......id_ип2
3.......id_ник2......id_ип1
4.......id_ник2......id_ип2


при этом пара полей id_NICK и id_IP вместе являются уникальными

Автор: alex82 22.3.2009, 3:28

А можно и вовсе одну таблицу создать. С первичным ключом по двум столбцам - IP и ник.

Автор: Setuper 22.3.2009, 3:33

Ну это смотря какие задачи)))

У меня в мульти-скрипте этого сделать невозможно)))

Простым программистам, в отличии от программистов баз данных, всегда хочется всё запихнуть в одну таблицу, при этом база данных становится не такой гибкой. Кроме этого, следует по возможности производить нормализацию базы данных и приведение её к нормальной форме Бойса-Кодда. Теория проектирования баз данных описывает алгоритмы правильного построения бд, другое дело, что не всегда получается им следовать, однако надо стараться это делать для того, чтобы получить наиболее эффективную базу данных, без избыточности и всяческий аномалий.

Автор: Wariner 25.3.2009, 20:25

Блин я как всегда туплю!

Код
    assert(con:execute[[
        CREATE TABLE IF NOT EXISTS `Nicks`(
        `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
        `Nick` VARCHAR(64) NOT NULL,
        PRIMARY KEY(`id`),
        UNIQUE(`Nick`)
    )
        CREATE TABLE IF NOT EXISTS `IPs`(
        `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
        `IP` VARCHAR(64) NOT NULL,
        PRIMARY KEY(`id`),
        UNIQUE(`IP`)
    )    
]])

ругается на синтаксис. чем разделить два запроса?

Автор: Setuper 25.3.2009, 20:56

Библиотека не предполагает выполнение двух запросов в одной транзакции. Для выполнения второго запроса должна быть закрыта первая транзакция.

Автор: Wariner 25.3.2009, 21:59

блин да что ж такое. когда берусь за своего бота ничего не пашет(((

Код
function OnStartup()
    assert(con:execute[[CREATE TABLE IF NOT EXISTS `Nicks`(`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,`Nick` VARCHAR(64) NOT NULL,PRIMARY KEY(`id`),    UNIQUE(`Nick`))]])
    assert(con:execute[[CREATE TABLE IF NOT EXISTS `IPs`(`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,`IP` VARCHAR(64) NOT NULL,PRIMARY KEY(`id`),    UNIQUE(`IP`))]])
    assert(con:execute[[CREATE TABLE IF NOT EXISTS `Users`(`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,`id_Nick` MEDIUMINT(10) NOT NULL,`id_IP` MEDIUMINT(10) NOT NULL,PRIMARY KEY(`id`))]])

....

function UserConnected(tUser)
    local Share = Core.GetUserValue(tUser, 16) or 0
    con:execute(("INSERT INTO `Nicks (`Nick`) VALUES ('%s')"):format(tUser.sNick))
    con:execute(("INSERT INTO `IPs (`IP`) VALUES ('%s')"):format(tUser.sIP))

не добавляет в базу и всё тут!

Автор: Setuper 25.3.2009, 22:02

Невнимательность просто
con:execute(("INSERT INTO `Nicks` (`Nick`) VALUES ('%s')"):format(tUser.sNick))

Автор: Wariner 26.3.2009, 17:26

есть код

Код
    con:execute(("INSERT INTO `Nicks` (`Nick`) VALUES ('%s')"):format(tUser.sNick))
    con:execute(("INSERT INTO `IPs` (`IP`) VALUES ('%s')"):format(tUser.sIP))
    con:execute(("INSERT INTO `Users` (`id_Nick`,`id_IP`) VALUES ((SELECT `id` FROM `Nicks` WHERE Nick = '%s'), (SELECT `id` FROM `IPs` WHERE IP = '%s'))"):format(tUser.sNick,tUser.sIP))

можно ли сделать проверку перед заносом данных в таблицу Users языком MySQL или это уже скриптом?

Автор: Setuper 26.3.2009, 17:44

База данных должна быть организована таким образом, чтобы все лишние проверки исключались. То есть нужно соблюдать целостность базы данных. Целостность базы данных заключается в объявлении уникальных атрибутов. База данных сама проверяет уникальные атрибуты, и если вносятся данные с уже существующим в таблице уникальным атрибутом, то база игнорирует внесение в таблицу таких данных.

Уникальность атрибутов может осуществляться для каждого атрибута в отдельности, а может осуществляться для группы атрибутов.
В рассматриваемой тобой таблице `Users`, по всей видимости, уникальность нужно придать группе атрибутов: `id_Nick` и `id_IP`, тогда при очередной вставке в эту таблицу будет проверяться существование двух указанных значений.

Автор: Wariner 26.3.2009, 21:34

с этим быстро разобрался. теперь есть:

Код
    assert(con:execute[[CREATE TABLE IF NOT EXISTS `Nicks`(`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,`Nick` VARCHAR(64) NOT NULL,PRIMARY KEY(`id`),    UNIQUE(`Nick`))]])
    assert(con:execute[[CREATE TABLE IF NOT EXISTS `IPs`(`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,`IP` VARCHAR(64) NOT NULL,PRIMARY KEY(`id`),    UNIQUE(`IP`))]])
    assert(con:execute[[CREATE TABLE IF NOT EXISTS `Users`(`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,`id_Nick` MEDIUMINT(10) NOT NULL,`id_IP` MEDIUMINT(10) NOT NULL,PRIMARY KEY(`id`),    UNIQUE(`id_Nick`,`id_IP`))]])
    assert(con:execute[[CREATE TABLE IF NOT EXISTS `MainLog`(`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,`DateTime` DATETIME NOT NULL, `id_User` MEDIUMINT(10) NOT NULL,`Msg` VARCHAR(64) NOT NULL,PRIMARY KEY(`id`))]])

и
Код
    if tCfg.MainLogs == 1 then
        local _,_,sData = string.find(sData, "%b<>%s+(.*)")
        con:execute(([[INSERT INTO `MainLog` (`DateTime`, `id_User`, `Msg`) VALUES ('%s', (SELECT `id` FROM `Users` WHERE
        (id_Nick = 'SELECT `id` FROM `Nicks` WHERE Nick = '%s'),(id_IP = 'SELECT `id` FROM `IPs` WHERE IP = '%s')), '%s')]]):format(os.date("%Y-%m-%d %H:%M:%S"),tUser.sNick, tUser.sIP, sData))
    end

в общем я хочу в таблицу лога главного чата записать ид юзера из таблицы Users. Получился громоздкий и неработающий код... Можно как то ужать?

Автор: alex82 26.3.2009, 21:57

Цитата
NOT NULL,PRIMARY KEY(`id`), UNIQUE(`IP`)

Т.е. и id и IP должны быть уникальными? Как-то не очень хорошо получается. А если зайдёт юзер с таким же IP?

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

Автор: Wariner 26.3.2009, 22:51

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

так как всё это делается при входе юзера то он 100% зареген! поэтому нужно id и именно из таблицы Users

Автор: Setuper 26.3.2009, 23:18

Всё верно, но вот только ты не совсем понял суть введения 3 таблиц, так как в твоём представленном варианте можно было вместо этих 3 таблиц записать 1 таблицу. Какой смысл несёт введение 3 таблиц у тебя? big_smile.gif Видимо ты просто повторил то, что я тебе сказал, но у меня всё по другому нежели у тебя, и смысл трёх таблиц заключается в идентификации аккаунта пользователя))))

Автор: Wariner 26.3.2009, 23:52

Цитата(Setuper @ 26.3.2009, 23:18) *
Какой смысл несёт введение 3 таблиц у тебя? big_smile.gif

снимает избыточность данных. я не знаю как это правильно выразить.... что я конкретно сделал не так?

Автор: Setuper 27.3.2009, 0:02

Ты прав, избыточность данных уничтожается. С точки зрения нормализации всё верно, однако с точки зрения здравого смысла избыточность такого рода заменилась избыточностью, выраженной в совпадении идентификаторов. По своей сути в этих трёх таблицах должны присутствовать ещё и другие поля, иначе смысл замены одной избыточности другой не понятен.
Если в таблицах Nicks и Ips присутствует по одному не ключевому атрибуту, то дробление на таблицы приводит к аномалиям в базе данных. В таблицах Nicks и Ips обязательно должны присутствовать 2 или более не ключевых атрибутов, тогда дробление оправдано.

Автор: Wariner 27.3.2009, 17:46

Как получить id последней строки таблицы?

на вот это ругается по синтаксису:

Код
local iNumb = assert(con:execute("LAST_INSERT_ID(`TextSeach`)"))
--или
local iNumb = assert(con:execute("mysql_insert_id(`TextSeach`)"))

Автор: Setuper 27.3.2009, 19:39

А для чего тебе это понадобилось?

Код
SELECT `id` FROM `table` ORDER BY `id` DESC LIMIT 1

Автор: Wariner 27.3.2009, 19:40

когда сделаю покажу. может ты подскажешь и другое решение)))

Автор: Wariner 5.4.2009, 13:14

Код
function SearchArrival(tUser, sData)
    sData = sData:sub(1,-2)
    local _,_,iNumber,sSeach = sData:find("$Search .-%s%u%p%u%p%d%p(%d+)%p(.*)")
    sSeach = String2Lower(sSeach)
    sSeach = sSeach:gsub("%p", " ")
    local _,_,sTthseach = sSeach:find("^(%a%a%a)")
    if sTthseach ~= "tth" then
        con:execute(("INSERT INTO `TextSeach` (`Seach`) VALUES ('%s')"):format(sSeach))
        con:execute(("UPDATE `TextSeach` SET '%s' = '%s' + 1 WHERE `Seach` = '%s'"):format("S"..tostring(iNumber), "S"..tostring(iNumber), sSeach))

где тут ошибка? инсертит но не апдейтит(((
создание таблицы:
Код
assert(con:execute[[CREATE TABLE IF NOT EXISTS `TextSeach`(`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,`Seach` VARCHAR(64) NOT NULL,PRIMARY KEY(`id`), `S1` MEDIUMINT(10) NOT NULL DEFAULT 0,
    `S2` MEDIUMINT(10) NOT NULL DEFAULT 0, `S3` MEDIUMINT(10) NOT NULL DEFAULT 0, `S4` MEDIUMINT(10) NOT NULL DEFAULT 0, `S5` MEDIUMINT(10) NOT NULL DEFAULT 0,
    `S6` MEDIUMINT(10) NOT NULL DEFAULT 0, `S7` MEDIUMINT(10) NOT NULL DEFAULT 0, `S8` MEDIUMINT(10) NOT NULL DEFAULT 0, `S10` MEDIUMINT(10) NOT NULL DEFAULT 0, UNIQUE(`Seach`))]])

Автор: Setuper 5.4.2009, 14:46

Код
assert(con:execute(("UPDATE `TextSeach` SET '%s' = '%s' + 1 WHERE `Seach` = '%s'"):format("S"..tostring(iNumber), "S"..tostring(iNumber), sSeach)))

Автор: Wariner 5.4.2009, 15:23

не помогло

Цитата
[16:22] Синтаксис TopSeach.lua:106: LuaSQL: Error executing query. MySQL: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''S1' = 'S1' + 1 WHERE `Seach` = 'test1'' at line 1


сделал всё с одинаковыми ковычками получил следующее
Код
[16:55] Синтаксис TopSeach.lua:106: LuaSQL: Error executing query. MySQL: Unknown column 'test1' in 'where clause'

Автор: Setuper 6.4.2009, 17:59

2Wariner:

Код
con:execute(("UPDATE `TextSeach` SET `S%s` = `S%s` + 1 WHERE `Seach` = '%s'"):format(tostring(iNumber), tostring(iNumber), sSeach))
Кавычки ' ' служат для обозначения вносимых строковых данных. Кавычки ` ` служат для обозначения имён полей, таблиц или баз данных. Метод format тут применяется для оптимизации, для избавления от излишней нагрузки на память конкатенацией, а ты всё равно пытаешься конкатенацию впихнуть. big_smile.gif

2vicious:
Код
function IsScriptRun()
  for k,v in ipairs(ScriptMan.GetScripts()) do
    if v.sName == "abc" and v.bEnabled == true then
      return true
    end
  end
end

Автор: Wariner 11.4.2009, 20:20

можно ли упростить функцию

Код
function ShowTopSeachDay(sDate)
    local tTemp = {}
    local sMsg = ""
    local sStr = string.rep("=",40)
    local cur = con:execute(("SELECT `id_Seach` FROM `S1` WHERE `date_Seach` = '%s'"):format(sDate))
    local row = cur:fetch({}, "a")
    while row do
        local cur2 = con:execute(("SELECT `Seach` FROM `TextSeach` WHERE `id` = '%s'"):format(row.id_Seach))
        local row2 = cur2:fetch({}, "a")
        while row2 do
            if not tTemp[row2.Seach] then
                tTemp[row2.Seach] = 1
            else
                tTemp[row2.Seach] = tTemp[row2.Seach] + 1
            end    
            row2 = cur2:fetch(row, "a")
        end    
        row = cur:fetch(row, "a")
    end
    for i,v in pairs(tTemp) do
        Core.SendToAll(i.."     "..v)
    end    
    cur:close()
        cur2:close()
  --  return ("%s\t%s\r\n"):format(sMsg,sStr)
end

основать её только на MySQL

Автор: Wariner 16.4.2009, 21:41

опять проблемы с MySQL((((
уже глаз замылился, где тут ошибка

Код
function UserDisconnected(tUser)
    con:execute(("UPDATE `NicksIPs` SET `out` = %s WHERE `id` = '(SELECT id FROM `NicksIPs` WHERE (`Nick` = '%s' && `IP` = '%s') ORDER BY id DESC LIMIT 1)'"):format(os.date("%Y-%m-%d"), tUser.sNick, tUser.sIP))     
end
OpDisconnected = UserDisconnected
RegDisconnected = UserDisconnected

создание таблицы
Код
assert(con:execute[[CREATE TABLE IF NOT EXISTS `NicksIPs`(`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,`Nick` VARCHAR(64) NOT NULL, `IP` VARCHAR(64) NOT NULL,`in` DATE NOT NULL, `out` DATE NOT NULL,PRIMARY KEY(`id`))]])

Автор: Setuper 16.4.2009, 21:50

Во-первых, `out` = '%s'
Во-вторых, в чём же ошибка? Что не так?

Автор: Wariner 16.4.2009, 21:57

да не апдейтится и всё

Автор: Setuper 16.4.2009, 22:07

ппц... а зачем такой гемор... не легче ли так написать:

Код
"UPDATE `NicksIPs` SET `out` = '%s' WHERE `Nick` = '%s' AND `IP` = '%s' LIMIT 1"

Автор: Wariner 16.4.2009, 22:13

оператор есть я на их сайте смотрел а гемор такой для потому что в таблице ип и ник позиции не уникальные и надо апдейтить именно последнюю запись!

Автор: Setuper 16.4.2009, 22:25

А как так может быть, что пара ник и ip не уникальны? Разве протокол позволяет находится на хабе двум пользователям с одним ником и ip ?
Что за бред?

Код
UNIQUE(`Nick`, `IP`)

Автор: Wariner 16.4.2009, 22:36

нет там просто интервалы нахождения пользователя на хабе! Объясняю:
когда входит юзер в таблицу NicksIPs записывается:
Ник_____IP____дата входа_______прочерк
при выходе прочерк должен заменится на дату выхода
при повторном коннекте юзера эта запись не перезаписывается а добавляется такая же еновая только с другими данными входа!

Автор: Setuper 17.4.2009, 1:11

И какой смысл в этом? Только гемор

Автор: Wariner 20.4.2009, 20:01

Может ли IP адрес менятся по ходу сессии. Т.е. если юзер входит с одним ип может ли он уходить с другим?

Автор: Setuper 20.4.2009, 21:18

По поводу смены ip адреса будет закрыт сокет, причем как со стороны сервера, так и со стороны клиента.

Шару точно так же.

Автор: Wariner 24.4.2009, 21:32

Есть таблица в которой отдельно присутствуют поля Дата и Время. Как построить запрос чтобы отыскать записи в промежутке с гггг-мм-дд чч:мм:сс до гггг-мм-дд чч:мм:сс?

Автор: PomanoB 24.4.2009, 22:02

Так попробуй:
WHERE `Data`>'гггг-мм-дд' AND `Data`<'гггг-мм-дд2' AND `Time`>'чч:мм:сс' AND `Time`<'чч:мм:сс2'
А вообще я всегда храню дату и время в формате UNIX, мне кажется так гораздо удобнее

Автор: Wariner 24.4.2009, 22:18

так пробовал, но что то не срослось)))) никакой сортировки...

Автор: PomanoB 24.4.2009, 22:19

Сортировка ORDER BY делается, добавь ORDER BY `id` в конце

Автор: Setuper 24.4.2009, 22:23

Согласен в Романовым, лучше записывать в бд unix время - os.time(), а из него можно уже "форматировать" время.
Тем более, ведь хаб и mysql сервер могут быть на разных машинах в разных странах, и время на серваке с mysql может отличаться от времени на хабе big_smile.gif

Автор: Wariner 24.4.2009, 22:23

не ты меня не понял! не отделились те сообщения которые не вошли в период времени...

Автор: arktik 26.11.2011, 8:29

Как мне исправить эту ошибку:

Код
LuaSQL: Error executing query. MySQL: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1818235298447e+14 WHERE name = 'share'' at line 1


Вот строки кода, дающие эту ошибку:
Код
function SetdbStatShare(iShare)
    if not con then Condb() end
    sIn = "UPDATE stats SET value="..tonumber(iShare).." WHERE name = 'share';"
    assert(con:execute((sIn)))
end


Почему в редких случаях в базу отправляется "1818235298447e+14", а не просто число, как должно быть?

ЗЫ: без преобразования tonumber() эта ошибка происходит всегда

Автор: Enyby 6.12.2011, 0:34

Ошибка происходит потому, что это неизвестный для MySQL тип значения. Нужно смотреть тип колонки value в таблице stats. Он должен быть BIGINT, а запрос должен быть:

Код
sIn = "UPDATE `stats` SET `value` = '"..iShare.."' WHERE `name` = 'share';"