質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Q&A

解決済

1回答

982閲覧

Go sqlite3で最新のレコードを任意の数残して削除する方法について

Mr.Morinonaka

総合スコア7

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

0グッド

0クリップ

投稿2019/08/27 10:42

編集2019/08/27 13:04

前提・実現したいこと

go言語でgo-sqlite3を用いてデータベースの任意のテーブルの最新のレコードを任意の数残して、それ以外のレコードをそのテーブルから削除すること。
テーブルは

Go

1cmd := fmt.Sprintf(` 2 CREATE TABLE IF NOT EXISTS %s ( 3 time DATETIME PRIMARY KEY NOT NULL, 4 name STRING, tableName) 5DbConnection.Exec(cmd)

のように作成しています。

発生している問題・エラーメッセージ

http://blog.kumacchi.com/2008/03/30/590
を参考に、下記のソースコードのように、レコードをtimeで降順にソートして、上から1500個を除いてselectしてdeleteするようにしてみたのですが、削除前も削除後もレコードの数が変わりません。
にも関わらず、なにもエラーが出ないので困っています。

該当のソースコード

Go

1func(c *params) Delete() error{ 2 //削除前のc.TableName()のレコード数の確認 3 countCmd:=fmt.Sprintf("SELECT COUNT(*) FROM %s",c.TableName()) 4 count,_:=DbConnection.Exec(countCmd) 5 realCount,_:=count.LastInsertId() 6 log.Println(c.TableName,"'s DataCount:",realCount) 7 8 //最新のレコード1500個を残して削除 9 deleteCmd := fmt.Sprintf("DELETE FROM %s WHERE time IN (SELECT time FROM %s ORDER BY time DESC LIMIT -1 OFFSET ?)",c.TableName(),c.TableName()) 10 _, err := DbConnection.Exec(deleteCmd,1500) 11 if err != nil { 12 log.Println("Could not delete sql data:",err) 13 return err 14 } 15 16     //削除後のc.TableName()のレコード数の確認 17 count,_=DbConnection.Exec(countCmd) 18 realCount,_=count.LastInsertId() 19 log.Println(c.TableName,"'s DataCount:",realCount) 20 21 return nil 22}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Mr.Morinonaka

2019/08/27 13:05

ご指摘ありがとうございます。 修正いたしました。 ここを利用するのは初めてでして、不慣れな部分が多いと思いますが、これからもよろしくお願いします。
guest

回答1

0

ベストアンサー

COMMIT or 失敗した時はROLLBACK が必要です。質問に提示したコード以外で COMMIT していますか?

投稿2019/08/27 14:10

Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Mr.Morinonaka

2019/08/27 17:06 編集

そもそもトランザクションを使っていないので、COMMITはしていません。 試しに、下記のようにデータ削除の前にトランザクションを開始し、その後にROLLBACKまたはCOMMITするように書き換えてみましたが、相変わらずデータ数は変わらず、エラーも出ませんでした。 tx, err := DbConnection.Begin() if err != nil { log.Println("action=DbConnection.Begin()",err) } deleteCmd := fmt.Sprintf("DELETE FROM %s WHERE time IN (SELECT time FROM %s ORDER BY time DESC LIMIT -1 OFFSET ?)",c.TableName(),c.TableName()) _, err = DbConnection.Exec(deleteCmd,1500) if err != nil { log.Println("Could not delete sql data:",err) tx.Rollback() return err } tx.Commit()
Orlofsky

2019/08/27 22:29

では、DELETEの中のSELECTでデータをSELECTできていますか? SELECT部分だけSQLを実行したら1500件分取得できますか?10件くらいの別テーブルを用意して LIMIT 5 でSQLをしてみては? 参考 https://www.dbonline.jp/mysql/select/index12.html
Mr.Morinonaka

2019/08/28 12:47 編集

せっかく協力してくださったのに大変申し訳ないのですが、結論から言うと実はちゃんと削除できていたみたいです。 どうやら、質問文のソースコードのレコード数の確認に用いていたプログラムが悪かったみたいです。 まず、毎秒sqlデータベースにレコードを1つ追記するプログラムなので、ファイルが大容量にならないように、レコードを追記するたびにその後(1500個以上にならないように)削除したかったのです。 ご指摘を受けて、下記のコードを用いて削除前のレコードを取得し、コンソールに中身を表示させてみたところ、一回実行されるたびに一つしか表示されませんでした。 selectCmd:=fmt.Sprintf("SELECT * FROM %s ORDER BY time DESC LIMIT -1 OFFSET ?",c.TableName()) rows, err := DbConnection.Query(selectCmd,1500) これは、レコードを1つ追加したためにレコード数が1501個になり、その後最新1500個を残して削除という処理が繰り返されているためだと考えました。 さらに、昨日取っておいたデータベースのバックアップファイルの容量と、現在のデータベースファイルの容量が変わらないため、ちゃんと削除が意図したように機能していると考えました。 となると、レコード数の確認のプログラムが間違っているようです。 一回実行されるたびにレコード数(?)のカウントは一つ増えているので、今までに追記したレコード数を示していると考えました。 どうやったら現在のレコード数が取得できるのかはこれから調べます。 大変助かりました。ありがとうございました。 またよろしくお願いいたします。
Orlofsky

2019/08/28 13:52

解決して良かったですね。暗黙のCOMMITだったようで。 この質問はクローズしてください。
Orlofsky

2019/08/28 20:33

自己解決されたので、ご自分で[回答]に書いてそこでベストアンサーにしましょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問