找不到存在的列

时间:2014-01-08 17:06:36

标签: android sqlite

我创建了一个名为“IsMine”列的表,但是当我尝试返回时,我的查询将无效:

 01-08 15:00:06.148: W/System.err(12453): android.database.sqlite.SQLiteException: no
such column: m.IsMine (code 1): , while compiling: SELECT r.RoomId, m.MessageContentId, 
m.Message, m.MsgDate, m.Sender, m.Receiver, m.IsMine FROM Room r LEFT JOIN ( SELECT 
 m1.MessageContentId, m1.RoomId, m1.Message, m1.MsgDate, m1.Sender, m1.Receiver FROM 
MessageContent m1 JOIN ( SELECT r1.RoomId, max(m2.MsgDate) maxMsgDate from Room r1 LEFT JOIN 
MessageContent m2 on r1.RoomId = m2.RoomId GROUP BY r1.RoomId) mf ON m1.RoomId =  mf.RoomId 
 AND m1.MsgDate = mf.maxMsgDate) m ON r.RoomId = m.RoomId

这是我的onCreate()函数和我用来返回对象的函数:

@Override
public void onCreate(SQLiteDatabase database) {
    String queryMessageContent = "CREATE TABLE MessageContent ( MessageContentId INTEGER PRIMARY KEY AUTOINCREMENT, RoomId INTEGER, Message TEXT, MsgDate DEFAULT CURRENT_TIMESTAMP, Sender TEXT, Receiver TEXT, IsMine INTEGER, FOREIGN KEY(RoomId) REFERENCES Room(RoomId))";
    database.execSQL(queryMessageContent);
}

public List<Room> getLastMessages() throws ParseException{
    List<Room> rooms = new ArrayList<Room>();
    StringBuilder query = new StringBuilder("SELECT r.RoomId, m.MessageContentId, m.Message, ");
    query.append("m.MsgDate, m.Sender, m.Receiver, m.IsMine ");
    query.append("FROM Room r ");
    query.append("LEFT JOIN ( ");
    query.append("SELECT m1.MessageContentId, m1.RoomId, m1.Message, m1.MsgDate, m1.Sender, m1.Receiver ");
    query.append("FROM MessageContent m1 ");
    query.append("JOIN ( ");
    query.append("SELECT r1.RoomId, max(m2.MsgDate) maxMsgDate from Room r1 ");
    query.append("LEFT JOIN MessageContent m2 on r1.RoomId = m2.RoomId GROUP BY r1.RoomId) mf ");
    query.append("ON m1.RoomId =  mf.RoomId AND m1.MsgDate = mf.maxMsgDate) m ");
    query.append("ON r.RoomId = m.RoomId ");
    SQLiteDatabase database = this.getWritableDatabase();


    Cursor cursor = database.rawQuery(query.toString(), null);
    if(cursor.moveToFirst()){
        do {
            Room room = new Room();
            MessageContent messageContent = new MessageContent();
            room.setId(cursor.getLong(0));
            messageContent.setMessageId(cursor.getLong(1));
            messageContent.setMessage(cursor.getString(2));
            messageContent.setDate(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").
                    parse(cursor.getString(3)));
            messageContent.setSender(cursor.getString(4));
            messageContent.setReceiver(cursor.getString(5));
            messageContent.setMine(Boolean.valueOf(cursor.getString(6)));
            room.getContent().add(messageContent);
            rooms.add(room);
        }while(cursor.moveToNext());
    }
    return rooms;

如何避免此错误?无论如何,我可以看到我的桌子(像DESC)?

3 个答案:

答案 0 :(得分:1)

您的查询实际上从未实际定义过m.IsMine。由于“m”在您的连接中定义,我相信您需要在引用它之前将其选择为“m”。这需要在第一个(m1)或第二个(r1 / m2)JOIN内发生(取决于你的表结构/逻辑)。

编辑: 就像我说的,我不确定你的逻辑,但是查询应该被修改为这样的结果:

SELECT r.RoomId, m.MessageContentId, m.Message, m.MsgDate, m.Sender, m.Receiver, m.IsMine
FROM Room r
LEFT JOIN
(
    SELECT m1.MessageContentId, m1.RoomId, m1.Message, m1.MsgDate, m1.Sender, m1.Receiver, m1.IsMine
    FROM MessageContent m1 
    JOIN
    ( 
        SELECT r1.RoomId, max(m2.MsgDate) maxMsgDate 
        FROM Room r1 
        LEFT JOIN MessageContent m2 on r1.RoomId = m2.RoomId GROUP BY r1.RoomId
    ) mf
    ON m1.RoomId =  mf.RoomId AND m1.MsgDate = mf.maxMsgDate
) m
ON r.RoomId = m.RoomId

答案 1 :(得分:1)

您正在从'm'中选择列IsMine,这是在查询中创建的内联表,但该内联表未选择IsMine,因此它不存在。使用SQL布局更容易看到:

SELECT
r.RoomId,
m.MessageContentId, 
m.Message,
m.MsgDate,
m.Sender,
m.Receiver,
m.IsMine    <-- Selecting it here from 'm'
FROM Room r LEFT JOIN
 ( SELECT 
   m1.MessageContentId,
   m1.RoomId,
   m1.Message,
   m1.MsgDate,
   m1.Sender,
   m1.Receiver    <-- But it isn't here in the columns returned for 'm'
   ,m1.IsMine  <-- Is that what you need?
   FROM MessageContent m1 JOIN 
     ( SELECT
       r1.RoomId,
       max(m2.MsgDate) maxMsgDate
       FROM Room r1
       LEFT JOIN MessageContent m2 ON r1.RoomId = m2.RoomId
       GROUP BY r1.RoomId
     ) mf ON m1.RoomId =  mf.RoomId 
         AND m1.MsgDate = mf.maxMsgDate
 ) m ON r.RoomId = m.RoomId

答案 2 :(得分:0)

狂野猜测:onCreate vs onUpgrade

可能是你一直在使用以前不同的表定义来处理这个相同的数据库吗?

这是一个非常疯狂的猜测,但我可以看到你在onCreate方法中创建表格。只是因为您知道只有当您尝试访问该数据库并且它尚不存在时才会调用此方法。因此,如果您在必须删除应用程序资源(在Android设备上)之前有另一个定义,或者使用onUpgrade方法来激活新定义。

一般提示:SQL验证

编辑:当使用SQL时,看看是否可以在独立的sqlite数据库中执行语句。这样,您无需运行Android应用即可验证SQL。

最简单的方法是使用sqlite中的命令行工具。有关详细信息,请查看sqlite docs