简体   繁体   English

当表2的某些行更新时,Sqlite触发器将更新表1

[英]Sqlite Trigger to Update table 1 when certain rows of table 2 is updated

I have two tables in sqlite in android: 我在android的sqlite中有两个表:

Table1: Outlets

id    pid   OutletName   Status
1      1    Tesco         1
2      1    Coors         1
3      2    Coors         1

Table2: projectparams 表2:projectparams

ppid projectname outletname  param          projStatus
1      RA_Pepsi   Tesco       shelfstrip       2
2      RA_Pepsi   Tesco       shelfleft        2
3      RA_Cocola  Coors       shelfstrip       1

Table1: For every PID (ProjectID) there are multiple Outlets stored in OutletName. 表1:对于每个PID(ProjectID),OutletName中存储了多个Outlet。

Table2: For each outlet there are multiple params stored in project params. 表2:对于每个出口,项目参数中存储了多个参数。

Whenever the user completes a task the param in Table2 is updated to 2. In the above example, when the user completes two tasks in Tesco, the status would be updated to 2 upon completion. 每当用户完成任务时,表2中的参数就会更新为2。在上面的示例中,当用户在Tesco中完成两个任务时,状态将在完成时更新为2。

I am trying to set the outlets status to 2 based on completion of tasks for every outlet. 我正在尝试根据每个网点的任务完成情况将网点状态设置为2。 In this example, when the status is updated to 2 in projectparam table, I want the Status in Outlets to be updated to 2 for the outlet Tesco. 在此示例中,当projectparam表中的状态更新为2时,我希望出口Tesco的Outlet中的状态更新为2。

I am using the following codes: 我正在使用以下代码:

triggered when the task gets completed. 任务完成时触发。

private void updateTaskStatus() {
        SQLiteDatabase db = sqLiteHelper.getWritableDatabase();
        String spinTextRecovered = spnTxt.getString("spinText", null);
        String updateTable = "update projectparams set projStatus=2 where param='"+spinTextRecovered+"' and projectName='"+projectName+"' and OutletName='"+outletName+"'";
        db.execSQL(updateTable);
        takePicButton.setEnabled( false );
    }

Triggered every time when the task gets completed and updates the outlet status when all the tasks for an outlet is completed. 每次任务完成时触发,并在插座的所有任务完成时更新插座状态。

   private void updateOutletStatus() {
        String query = "select OutletName from projectparams where projectName= '"+projectName+"' and OutletName= '"+outletName+"' group by projStatus";
        if (sqLiteHelper.getData(query).getCount()==1) {
            Toast.makeText( getApplicationContext(), "No more tasks in this outlet!", Toast.LENGTH_SHORT ).show();
            SQLiteDatabase db = sqLiteHelper.getWritableDatabase();
            String outletUpdate = "update outlets set Status=2 where OutletName='"+outletName+"' and pid = (select id from projects where ProjectName = '"+projectName+"' ) ";
            db.execSQL(outletUpdate);
        }
    }

The above code works...however since I am using an intent to display the projects, outlets and task parameters, many times i find the updation of outlet not happening. 上面的代码可以工作...但是,由于我使用意图显示项目,出口和任务参数,因此很多次我都没有发现出口的更新。

Can i write this better? 我可以写得更好吗? Can someone guide me to use triggers? 有人可以指导我使用触发器吗?

I believe your core issue is that the query 我相信您的核心问题是查询

String query = "select OutletName from projectparams where projectName= '"+projectName+"' and OutletName= '"+outletName+"' group by projStatus";

Will return 1 not only if all the projects have completed but also if none have been completed (ie all the projStatus values are 1). 不仅在所有项目都已完成的情况下,而且在所有项目都未完成的情况下(即,所有projStatus值为1),将返回1。

Additionally, as it stands if very much appears that the Outlets table is superfluous. 此外,就目前而言,似乎Outlets表是多余的。 That is all columns (bar the id, which serves no purpose) are duplicated in the projectparams table. 那就是在projectparams表中重复了所有列(没有ID的列)。

You can ascertain is all the tasks for a project by multiplying the number of params by 2 (the status completion value) against the sum of all of the projstatus values. 通过将参数数量乘以所有projstatus值的总和乘以2(状态完成值),可以确定项目的所有任务。 If they match then all params have been set to 2. 如果它们匹配,则所有参数都设置为2。

Consider the following which is your data (but status 1 for RA_Perpsi/Tesco rows) plus some additional data where the only fully completed is for the Completed Example project (highlighted) as per :- 考虑以下是您的数据(但RA_Perpsi / Tesco行的状态为1)以及一些其他数据,其中唯一完全完成的是已完成示例项目(突出显示),具体如下:

在此处输入图片说明

The using (to process all results) 使用(处理所有结果)

-- WHERE clause removed group by projectname added (to show all results)
SELECT OutletName FROM projectparams GROUP BY projectname,projStatus;

The result is :- 其结果是:-

在此处输入图片说明

  • That is Ra_Pepsi/Tesco has no params completed (nothing done) but there is only one row so the project is detected as being completed. 也就是说Ra_Pepsi / Tesco没有完成参数(什么都没有完成),但是只有一行,因此该项目被检测为完成。 Likewise for RA_Cocola and for Some other outlet. 对于RA_Cocola和其他出口也是如此。
  • Completed Example produces 1 row so is complete as it should be. Completed Example产生1行,因此应该是完整的。 Incomplete example (where it is part way through) is the only one that comes up as incomplete. 不完整的示例(其中一部分是通过的)是唯一不完整的示例。

Using the above data consider the following (noting that no reference is needed to the Outlets table AND that the WHERE clause has been omitted and the GROUP BY according to projectname to show all projects) :- 使用以上数据,请考虑以下内容(注意,无需引用Outlets表,并且已省略WHERE子句,并且根据项目名称显示GROUP BY以显示所有项目):

SELECT 
    OutletName, 
    CASE 
        WHEN (count() * 2 - sum(projStatus)) = 0 THEN 2 ELSE 1
        END AS Status,
    (count() * 2 - sum(projStatus)) ||' of '||count() AS outstanding 
FROM projectparams 
GROUP BY projectname

This results in :- 结果是:

在此处输入图片说明

As such there is no need for the Outlet Table the projectparams table, at least according to your example, is sufficient and as such there is no need for a trigger. 这样,至少根据您的示例,就不需要Outlet表,projectparams表就足够了,因此,不需要触发器。 Whenever an update is made you simply refresh the display using the one table and a query such as the last example. 每当进行更新时,您只需使用一个表和一个查询(例如上一个示例)来刷新显示。

To demonstrate your scenario step by step consider the following code (based upon the data above ie the RA_Pepsi has been added but nothing done) :- 为了逐步演示您的方案,请考虑以下代码(基于上面的数据,即已添加RA_Pepsi,但未执行任何操作):-

-- First Query
SELECT 
    OutletName, 
    CASE 
        WHEN (count() * 2 - sum(projStatus)) = 0 THEN 2 ELSE 1
        END AS Status,
    (count() * 2 - sum(projStatus)) ||' of '||count() AS outstanding 
FROM projectparams 
WHERE projectname = 'RA_Pepsi'AND outletName = 'Tesco'
GROUP BY projectname
;

-- First Update
UPDATE projectparams SET projStatus = 2 WHERE param = 'shelfstrip' AND projectname = 'RA_Pepsi' AND outletName = 'Tesco';

-- 2nd Query
SELECT 
    OutletName, 
    CASE 
        WHEN (count() * 2 - sum(projStatus)) = 0 THEN 2 ELSE 1
        END AS Status,
    (count() * 2 - sum(projStatus)) ||' of '||count() AS outstanding 
FROM projectparams 
WHERE projectname = 'RA_Pepsi'AND outletName = 'Tesco'
GROUP BY projectname
;

-- 2nd Update (all completed) 
UPDATE projectparams SET projStatus = 2 WHERE param = 'shelfleft' AND projectname = 'RA_Pepsi' AND outletName = 'Tesco';


-- 3rd Query
SELECT 
    OutletName, 
    CASE 
        WHEN (count() * 2 - sum(projStatus)) = 0 THEN 2 ELSE 1
        END AS Status,
    (count() * 2 - sum(projStatus)) ||' of '||count() AS outstanding 
FROM projectparams 
WHERE projectname = 'RA_Pepsi'AND outletName = 'Tesco'
GROUP BY projectname
;

The first query shows the project with nothing done as per :- 第一个查询显示项目,但没有按照以下步骤进行:

在此处输入图片说明

The 2nd query (after changing the status of the shelfstrip to 2) shows :- 第二个查询(将架子带的状态更改为2后)显示:-

在此处输入图片说明

The 3rd query (after changing the status of the shelfleft to 2) shows :- 第三个查询(将架子左侧的状态更改为2后)显示:-

在此处输入图片说明

For Android 对于Android

The foloowing code demonstrates applying the above on Android and additional uses the recommended convenience methods (they build much of the SQL, off protection against SQL injection and add additional functionality eg update returns the number of rows updated) :- 以下代码演示了如何在Android上应用上述方法,以及如何使用其他推荐的便捷方法(它们构建了大量SQL,针对SQL注入提供了防护,并添加了其他功能,例如update返回更新的行数):

Two methods (the first using the query above, the second updating as per yours but using the update convenience method :- 两种方法(第一种使用上面的查询,第二种根据您的情况进行更新,但使用update便捷方法:-

public String getOutletStatus(String projectname, String outletname) {
    String rv = "Ooops nothing found!"; // default if nothing found
    String[] columns = new String[]{"outletname",
            "CASE " +
                    "WHEN (count() * 2 - sum(projStatus)) = 0 THEN 2 ELSE 1 " +
                    "END AS Status", //<<<<<<<<< the column name will be Status
            "(count() * 2 - sum(projStatus)) ||' of '||count() AS outstanding" // The column name will be outstanding
    };
    String whereclause = "projectname=? AND outletName=?";
    String[] whereargs = new String[]{projectname,outletname};
    String groupby = "projectname"; // not needed
    Cursor csr = sqliteHelper.getWritableDatabase().query("projectparams",columns,whereclause,whereargs,null,null,null);
    if (csr.moveToFirst()) {
        int statuscode = csr.getInt(csr.getColumnIndex("Status"));
        String outstanding = csr.getString(csr.getColumnIndex("outstanding"));
        String outlet = csr.getColumnName(csr.getColumnIndex("outletname"));
        String statusdescription = "incomplete";
        if (statuscode == 2) {
            statusdescription = "complete";
        }
        rv = "The status of project " + projectname + " for outlet " + outlet + " is " + statusdescription + ". With " + outstanding + ".";
    }
    csr.close();
    return rv;
}

public void updateStatus(String projectname, String outletname, String param) {
    String whereclause = "projectname=? AND outletname=? AND param=?";
    String[] whereargs = new String[]{projectname,outletname,param};
    ContentValues cv = new ContentValues();
    cv.put("projStatus",2);
    int number_of_rows_updated = sqliteHelper.getWritableDatabase().update("projectparams",cv,whereclause,whereargs);
}

They have been tested (using the base data show above) and reflect the final 3 queries with updates between them :- 它们已经过测试(使用上面显示的基础数据),并且反映了最后3个查询以及它们之间的更新:-

    String status = getOutletStatus("RA_Pepsi","Tesco"); // Before anything
    Log.d("RESULT",status);

    updateStatus("RA_Pepsi","Tesco","shelfstrip"); //shelfstrip completed
    status = getOutletStatus("RA_Pepsi","Tesco");
    Log.d("RESULT",status);

    updateStatus("RA_Pepsi","Tesco","shelfleft"); //shelfleft completed
    status = getOutletStatus("RA_Pepsi","Tesco");
    Log.d("RESULT",status);

Result in the Log :- 结果在日志中:

04-29 12:46:09.615 20471-20471/? D/RESULT: The status of project RA_Pepsi for outlet outletname is incomplete. With 2 of 2.
04-29 12:46:09.621 20471-20471/? D/RESULT: The status of project RA_Pepsi for outlet outletname is incomplete. With 1 of 2.
04-29 12:46:09.625 20471-20471/? D/RESULT: The status of project RA_Pepsi for outlet outletname is complete. With 0 of 2.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM