提要表 2 和表 1 数据 SQLite Android Studio

Posted

技术标签:

【中文标题】提要表 2 和表 1 数据 SQLite Android Studio【英文标题】:Feed table 2 with table one data SQLite Android Studio 【发布时间】:2021-09-21 02:59:51 【问题描述】:

我正在尝试创建一个烘焙销售费用的应用程序,我可以在其中单独输入烘焙过程中使用的成分的值,然后使用每个配方中成分的值输入每个产品的值,所以我可以看到我可以卖多少才能获得丰厚的利润。 我有一个数据库和方法在我的第一个表(保存、删除、更新、搜索...)上工作,但我不能让我的第二个表(TABLE_RECEITA)使用我的第一个表(TABLE_PRODUTO)中已经存在的数据,补充我的食谱。 我想用我的第一个表列中的数据在它的列上提供我的第二个表,只更改数量的数据,并通过根据使用的数量进行划分来更改值。 我尝试使用外键和微调器,但没有成功,但很有可能我做错了什么。

我的数据库:

package com.myapplication.umdocededaisy;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MyDatabase extends SQLiteOpenHelper 

    List<MateriaPrima> listaProduto = new ArrayList<>();
    List<Receita> listaReceita = new ArrayList<>();

    private final Context context;
    private static final String DATABASE_NAME = "BancoDoceDaisy.db";
    private static final int DATABASE_VERSION = 9;

    //Estruturas das Tabelas do banco de dados:

    //Tabela dos produtos - materia prima **(FIRST TABLE)**:
    private static final String TABLE_PRODUTO = "materia_prima";
    private static final String COLUMN_CODIGO = "codigo";
    private static final String COLUMN_PRODUTO = "produto";
    private static final String COLUMN_VALOR = "valor";
    private static final String COLUMN_QTD = "quantidade";
    private static final String COLUMN_TIPO = "tipo";
    //------------------------------------------------------
    //Tabela de receitas/massas - **(SECOND TABLE)**:
    private static final String TABLE_RECEITA = "receitas";
    private static final String COLUMN_TITULO = "titulo";
    private static final String COLUMN_ITEM1 = "item1";
    private static final String COLUMN_ITEM2 = "item2";
    private static final String COLUMN_ITEM3 = "item3";
    private static final String COLUMN_ITEM4 = "item4";
    private static final String COLUMN_ITEM5 = "item5";
    private static final String COLUMN_ITEM6 = "item6";
    private static final String COLUMN_ITEM7 = "item7";
    private static final String COLUMN_ITEM8 = "item8";
    private static final String COLUMN_ITEM9 = "item9";
    private static final String COLUMN_ITEM10 = "item10";
    private static final String COLUMN_ITEM11 = "item11";
    private static final String COLUMN_ITEM12 = "item12";
    private static final String COLUMN_ITEM13 = "item13";
    private static final String COLUMN_ITEM14 = "item14";
    private static final String COLUMN_VALOR1 = "valor1";
    private static final String COLUMN_VALOR2 = "valor2";
    private static final String COLUMN_VALOR3 = "valor3";
    private static final String COLUMN_VALOR4 = "valor4";
    private static final String COLUMN_VALOR5 = "valor5";
    private static final String COLUMN_VALOR6 = "valor6";
    private static final String COLUMN_VALOR7 = "valor7";
    private static final String COLUMN_VALOR8 = "valor8";
    private static final String COLUMN_VALOR9 = "valor9";
    private static final String COLUMN_VALOR10 = "valor10";
    private static final String COLUMN_VALOR11 = "valor11";
    private static final String COLUMN_VALOR12 = "valor12";
    private static final String COLUMN_VALOR13 = "valor13";
    private static final String COLUMN_VALOR14 = "valor14";
    private static final String COLUMN_QTD1 = "qtd1";
    private static final String COLUMN_QTD2 = "qtd2";
    private static final String COLUMN_QTD3 = "qtd3";
    private static final String COLUMN_QTD4 = "qtd4";
    private static final String COLUMN_QTD5 = "qtd5";
    private static final String COLUMN_QTD6 = "qtd6";
    private static final String COLUMN_QTD7 = "qtd7";
    private static final String COLUMN_QTD8 = "qtd8";
    private static final String COLUMN_QTD9 = "qtd9";
    private static final String COLUMN_QTD10 = "qtd10";
    private static final String COLUMN_QTD11 = "qtd11";
    private static final String COLUMN_QTD12 = "qtd12";
    private static final String COLUMN_QTD13 = "qtd13";
    private static final String COLUMN_QTD14 = "qtd14";


    MyDatabase(Context context) 
        super(context, DATABASE_NAME,null, DATABASE_VERSION);
        this.context = context;
    

    @Override
    public void onCreate(SQLiteDatabase db) 
        String query = "CREATE TABLE "+ TABLE_PRODUTO +
                " (" + COLUMN_CODIGO + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COLUMN_PRODUTO + " TEXT, " +
                COLUMN_VALOR + " FLOAT, " +
                COLUMN_QTD + " FLOAT, " +
                COLUMN_TIPO + " TEXT); ";
        db.execSQL(query);

        String query2 = "CREATE TABLE "+ TABLE_RECEITA +
                " (" + COLUMN_TITULO + " TEXT PRIMARY KEY, " + COLUMN_ITEM1 + "TEXT," + COLUMN_ITEM2 + " TEXT, " +
                COLUMN_ITEM3 + " TEXT, " + COLUMN_ITEM4 + " TEXT, " + COLUMN_ITEM5 + " TEXT, " + COLUMN_ITEM6 + " TEXT, " +
                COLUMN_ITEM7 + " TEXT, " + COLUMN_ITEM8 + " TEXT, " + COLUMN_ITEM9 + " TEXT, " + COLUMN_ITEM10 + " TEXT, " +
                COLUMN_ITEM11 + " TEXT, " + COLUMN_ITEM12 + " TEXT, " + COLUMN_ITEM13 + " TEXT, " + COLUMN_ITEM14 + " TEXT, " +
                COLUMN_VALOR1 + "FLOAT, " + COLUMN_VALOR2 + "FLOAT, " +COLUMN_VALOR3 + "FLOAT, " + COLUMN_VALOR4 + "FLOAT, " +
                COLUMN_VALOR5 + "FLOAT, " + COLUMN_VALOR6 + "FLOAT, " + COLUMN_VALOR7 + "FLOAT, " + COLUMN_VALOR8 + "FLOAT, " +
                COLUMN_VALOR9 + "FLOAT, " + COLUMN_VALOR10 + "FLOAT, " + COLUMN_VALOR11 + "FLOAT, " + COLUMN_VALOR12 + "FLOAT, " +
                COLUMN_VALOR13 + "FLOAT, " + COLUMN_VALOR14 + "FLOAT, " + COLUMN_QTD1 + "FLOAT, " + COLUMN_QTD1 + "FLOAT, " +
                COLUMN_QTD1 + "FLOAT, " + COLUMN_QTD2 + "FLOAT, " + COLUMN_QTD3 + "FLOAT, " + COLUMN_QTD4 + "FLOAT, " +
                COLUMN_QTD5 + "FLOAT, " + COLUMN_QTD6 + "FLOAT, " + COLUMN_QTD7 + "FLOAT, " + COLUMN_QTD8 + "FLOAT, " +
                COLUMN_QTD9 + "FLOAT, " + COLUMN_QTD10 + "FLOAT, " + COLUMN_QTD11 + "FLOAT, " + COLUMN_QTD12 + "FLOAT, " +
                COLUMN_QTD13 + "FLOAT, " + COLUMN_QTD14 + "FLOAT); ";
                db.execSQL(query2);
    

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_PRODUTO);
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_RECEITA);
        onCreate(db);
    

    void addProduto(MateriaPrima materiaPrima) 
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();

        cv.put(COLUMN_PRODUTO, materiaPrima.getProduto());
        cv.put(COLUMN_VALOR, materiaPrima.getValor());
        cv.put(COLUMN_QTD, materiaPrima.getQuantidade());
        cv.put(COLUMN_TIPO, materiaPrima.getTipo());

        long result = db.insert(TABLE_PRODUTO, null, cv);
        if (result == -1) 
            Toast.makeText(context, R.string.strFailed, Toast.LENGTH_SHORT).show();
        else 
            Toast.makeText(context, R.string.strAddSucess, Toast.LENGTH_SHORT).show();
        
        db.close();
    

    void addReceita(Receita receita) 
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();

        cv.put(COLUMN_TITULO, receita.getTitulo());
        cv.put(COLUMN_ITEM1, receita.getItem1());
        cv.put(COLUMN_ITEM2, receita.getItem2());
        cv.put(COLUMN_ITEM3, receita.getItem3());
        cv.put(COLUMN_ITEM4, receita.getItem4());
        cv.put(COLUMN_ITEM5, receita.getItem5());
        cv.put(COLUMN_ITEM6, receita.getItem6());
        cv.put(COLUMN_ITEM7, receita.getItem7());
        cv.put(COLUMN_ITEM8, receita.getItem8());
        cv.put(COLUMN_ITEM9, receita.getItem9());
        cv.put(COLUMN_ITEM10, receita.getItem10());
        cv.put(COLUMN_ITEM11, receita.getItem11());
        cv.put(COLUMN_ITEM12, receita.getItem12());
        cv.put(COLUMN_ITEM13, receita.getItem13());
        cv.put(COLUMN_ITEM14, receita.getItem14());
        cv.put(COLUMN_VALOR1, receita.getValor1());
        cv.put(COLUMN_VALOR2, receita.getValor2());
        cv.put(COLUMN_VALOR3, receita.getValor3());
        cv.put(COLUMN_VALOR4, receita.getValor4());
        cv.put(COLUMN_VALOR5, receita.getValor5());
        cv.put(COLUMN_VALOR6, receita.getValor6());
        cv.put(COLUMN_VALOR7, receita.getValor7());
        cv.put(COLUMN_VALOR8, receita.getValor8());
        cv.put(COLUMN_VALOR9, receita.getValor9());
        cv.put(COLUMN_VALOR10, receita.getValor10());
        cv.put(COLUMN_VALOR11, receita.getValor11());
        cv.put(COLUMN_VALOR12, receita.getValor12());
        cv.put(COLUMN_VALOR13, receita.getValor13());
        cv.put(COLUMN_VALOR14, receita.getValor14());
        cv.put(COLUMN_QTD1, receita.getQtd1());
        cv.put(COLUMN_QTD2, receita.getQtd2());
        cv.put(COLUMN_QTD3, receita.getQtd3());
        cv.put(COLUMN_QTD4, receita.getQtd4());
        cv.put(COLUMN_QTD5, receita.getQtd5());
        cv.put(COLUMN_QTD6, receita.getQtd6());
        cv.put(COLUMN_QTD7, receita.getQtd7());
        cv.put(COLUMN_QTD8, receita.getQtd8());
        cv.put(COLUMN_QTD9, receita.getQtd9());
        cv.put(COLUMN_QTD10, receita.getQtd10());
        cv.put(COLUMN_QTD11, receita.getQtd11());
        cv.put(COLUMN_QTD12, receita.getQtd12());
        cv.put(COLUMN_QTD13, receita.getQtd13());
        cv.put(COLUMN_QTD14, receita.getQtd14());

        long result = db.   insert(TABLE_RECEITA, null, cv);
        if (result == -1) 
            Toast.makeText(context, R.string.strFailed, Toast.LENGTH_SHORT).show();
        else 
            Toast.makeText(context, R.string.strAddSucess, Toast.LENGTH_SHORT).show();
        
        db.close();
    

    public List<MateriaPrima> buscaProduto() 
        String[] columns = COLUMN_CODIGO, COLUMN_PRODUTO, COLUMN_VALOR, COLUMN_QTD, COLUMN_TIPO;
        SQLiteDatabase db = getReadableDatabase();
        @SuppressLint("Recycle") Cursor cursor = db.query(TABLE_PRODUTO, columns, null, null, null,null, null);

        while (cursor.moveToNext()) 
            int index1 = cursor.getColumnIndex(COLUMN_CODIGO);
            int codigo = cursor.getInt(index1);
            int index2 = cursor.getColumnIndex(COLUMN_PRODUTO);
            String produto = cursor.getString(index2);
            int index3 = cursor.getColumnIndex(COLUMN_VALOR);
            float valor = cursor.getFloat(index3);
            int index4 = cursor.getColumnIndex(COLUMN_QTD);
            float quantidade = cursor.getFloat(index4);
            int index5 = cursor.getColumnIndex(COLUMN_TIPO);
            String tipo = cursor.getString(index5);
            MateriaPrima produtos = new MateriaPrima(codigo, produto, valor, quantidade, tipo);
            listaProduto.add(produtos);
        
        return listaProduto;
    

    public List<Receita> buscaReceita() 
        String[] columns = COLUMN_TITULO, COLUMN_ITEM1, COLUMN_VALOR, COLUMN_QTD, COLUMN_TIPO;
        SQLiteDatabase db = getReadableDatabase();
        @SuppressLint("Recycle") Cursor cursor = db.query(TABLE_RECEITA, columns, null, null, null,null, null);

        while (cursor.moveToNext()) 
            int index1 = cursor.getColumnIndex(COLUMN_TITULO);
            String titulo = cursor.getString(index1);
            int index2 = cursor.getColumnIndex(COLUMN_ITEM1);
            String item1 = cursor.getString(index2);
            /*int index3 = cursor.getColumnIndex(COLUMN_VALOR);
            float valor = cursor.getFloat(index3);
            int index4 = cursor.getColumnIndex(COLUMN_QTD);
            float quantidade = cursor.getFloat(index4);
            int index5 = cursor.getColumnIndex(COLUMN_TIPO);
            String tipo = cursor.getString(index5);*/
            Receita receitas = new Receita(titulo, item1); //, valor, quantidade, tipo);
            listaReceita.add(receitas);
        
        return listaReceita;
    

    void updateData(String row_id, String produto, String valor, String quantidade, String tipo)
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(COLUMN_PRODUTO, produto);
        cv.put(COLUMN_VALOR, valor);
        cv.put(COLUMN_QTD, quantidade);
        cv.put(COLUMN_TIPO, tipo);

        long result = db.update(TABLE_PRODUTO, cv, "codigo=?", new String[]row_id);
        if(result == -1)
            Toast.makeText(context, R.string.strFailed, Toast.LENGTH_SHORT).show();
         else
            Toast.makeText(context, R.string.strSucess, Toast.LENGTH_SHORT).show();
        

        db.close();
    

   
    void deleteOneRow(String row_id)
        SQLiteDatabase db = this.getWritableDatabase();
        long result = db.delete(TABLE_PRODUTO, "codigo=?", new String[]row_id);
        if(result== -1)
            Toast.makeText(context, R.string.strFailed, Toast.LENGTH_SHORT).show();
        else 
            Toast.makeText(context, R.string.strSucess, Toast.LENGTH_SHORT).show();
        

    

    void deleteAllData() 
        SQLiteDatabase db = this.getWritableDatabase();
        db.execSQL("DELETE FROM " + TABLE_PRODUTO);
        db.close();
    

使用第一张桌子上保存的食材保存我的食谱(第二张桌子)的活动:

package com.myapplication.umdocededaisy;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;

public class AddItem extends AppCompatActivity 
    EditText et_produto, et_valor, et_qtd, et_sqtd, et_tipo, et_stipo;
    Button btnIncluir;
    String produto, valor, quantidade, tipo;
    List<MateriaPrima> listaProdutos;
    Spinner spinner;
    MyDatabase myDB = new MyDatabase(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_item);

        //Declarações objetos:
        et_produto = findViewById(R.id.et_produto);
        et_valor = findViewById(R.id.et_valor);
        et_qtd = findViewById(R.id.et_qtd);
        et_sqtd = findViewById(R.id.et_sqtd);
        et_tipo = findViewById(R.id.et_tipo);
        et_stipo = findViewById(R.id.et_stipo);
        btnIncluir = findViewById(R.id.btnIncluir);
        spinner = findViewById(R.id.spinner);

        //Chamada de Métodos:
        getAndSetIntentData();
        loadSpinnerData();
        loadSpinner();


        //Botões:
        //Save Button to Second Table:
        btnIncluir.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                Receita receita = new Receita();
                

                myDB.addReceita(receita);
            
        );
    

    void getAndSetIntentData() 
        if (getIntent().hasExtra("produto") && getIntent().hasExtra("valor") &&
                getIntent().hasExtra("quantidade") && getIntent().hasExtra("tipo"))
            //Getting data:
            produto = getIntent().getStringExtra("produto");
            valor = getIntent().getStringExtra("valor");
            quantidade = getIntent().getStringExtra("quantidade");
            tipo = getIntent().getStringExtra("tipo");

            //Setting data:
            et_produto.setText(produto);
            et_valor.setText(valor);
            et_qtd.setText(quantidade);
            et_tipo.setText(tipo);
            et_stipo.setText(tipo);

        else
            Toast.makeText(this, R.string.strData0, Toast.LENGTH_SHORT).show();
        
    

我不知道如何编写代码来保存这些更改,我不知道我是否必须在我的数据库插入方法或只是在这里更改某些内容,因为我的插入方法与我的插入方法一样第一张表。

我的 AddProduto(我将配料保存在第一张桌子上):

package com.myapplication.umdocededaisy;

import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

public class AddProduto extends AppCompatActivity 

    EditText editProduto, editValor, editQuantidade, editTipo;
    FloatingActionButton btnVoltar;
    Button btnSalvar;
    InputMethodManager inputManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_produto);

        //Declarações objetos:
        editProduto = findViewById(R.id.editProduto);
        editValor = findViewById(R.id.editValor);
        editQuantidade = findViewById(R.id.editQuantidade);
        editTipo = findViewById(R.id.editTipo);
        btnVoltar = findViewById(R.id.btnVoltar);
        btnSalvar = findViewById(R.id.btnSalvar);
        inputManager = (InputMethodManager) getSystemService (Context.INPUT_METHOD_SERVICE);

        btnVoltar.setOnClickListener(v -> 
            Intent voltar = new Intent(AddProduto.this, MainActivity.class);
            startActivity(voltar);
        );

        btnSalvar.setOnClickListener(v -> 
            if(editProduto.getText().toString().isEmpty() || editValor.getText().toString().isEmpty() ||
                    editQuantidade.getText().toString().isEmpty() || editTipo.getText().toString().isEmpty())
            
                Toast.makeText(AddProduto.this, R.string.strEmpty, Toast.LENGTH_SHORT).show();
            else
            MyDatabase myDB = new MyDatabase(AddProduto.this);
                MateriaPrima materiaPrima = new MateriaPrima();
                materiaPrima.setProduto(editProduto.getText().toString());
                materiaPrima.setValor(Float.parseFloat(editValor.getText().toString()));
                materiaPrima.setQuantidade(Float.parseFloat(editQuantidade.getText().toString()));
                materiaPrima.setTipo(editTipo.getText().toString());
                myDB.addProduto(materiaPrima);
        
            reset();
            editProduto.requestFocus(); //focar no campo especificado
            inputManager.hideSoftInputFromWindow(btnSalvar.getWindowToken(), 0);
    );

    
    void reset()
        editProduto.setText(" ");
        editValor.setText(" ");
        editQuantidade.setText(" ");
        editTipo.setText(" ");


谁能帮帮我? 我到处寻找,但没有找到任何可以应用于我的案例的东西。 提前致谢。

【问题讨论】:

【参考方案1】:

我不知道如何编写代码来保存这些更改,

您的数据库的设计似乎引入了复杂性,这会使在第二个表中插入和检索数据变得相当复杂。

从外观上看,您的第二个表由许多列组成,其中关系可以替换重复的列(材料/成分),添加这样的关系可能会简化问题。

要查看此内容,您有材料(成分),例如牛奶面粉糖等。一种成分可以用于许多食谱,而一个食谱可以使用多种成分。因此,您可能希望食谱和成分之间存在多对多关系。

所以我建议你考虑一个映射表,它允许你有一个多对多关系,所以 3 个表而不是 2 个。也许考虑以下:-

CREATE TABLE IF NOT EXISTS materia_prima (codigo INTEGER PRIMARY KEY /* AUTOINCREMENT */,produto TEXT, VALOR FLOAT, QTD FLOAT, TIPO TEXT);
CREATE TABLE IF NOT EXISTS receitas (TITULO TEXT PRIMARY KEY);
CREATE TABLE IF NOT EXISTS receitas_materia (
    titulo_map TEXT REFERENCES receitas(titulo) ON DELETE CASCADE ON UPDATE CASCADE,
    materia_map INTEGER REFERENCES materia_prima(codigo) ON DELETE CASCADE ON UPDATE CASCADE, receitas_materia_qtd FLOAT, 
    PRIMARY KEY(titulo_map,materia_map));
materia_prima 表保持原样(除了不需要低效的 AUTOINCREMENT,因此已将其注释掉) receitas 表已大大简化(仅 1 列) receitas_materia 表是映射表,用于表示配方使用的成分。 已添加外键约束(REFERENCES 子句)以强制参照完整性。 ON DELETE/UPDATE 表示将更改从父级传播到子级。 已添加第三列来表示配方使用的数量。

因此,进一步添加以下数据:-

首先是一些成分,包括每份的成本:-

INSERT INTO materia_prima VALUES 
    (null,'Plain Flour',0.54,1,'Gram'),
    (null,'SR Flour',0.55,1,'Gram'),
    (null,'Eggs',1.34,1,'Each'),
    (null,'Milk',0.2,1,'MilliLitre'),
    (null,'Sugar',0.65,1,'Gram');

第二个食谱:-

INSERT INTO receitas VALUES ('Bread'),('Cake'),('Scone');

现在食谱使用的成分(只是面包和蛋糕):-

INSERT INTO receitas_materia VALUES 
    ('Bread',1 /*map to Plain Flour*/,200 /* uses 200 grams */),
    ('Bread',3,2),
    ('Bread',4,50),
    ('Bread',5,10),
    
    ('Cake',2,400),
    ('Cake',3,3),
    ('Cake',4,100),
    ('Cake',5,300)
;
因此,而不是许多列和尝试确定哪些内容进入哪个列的复杂性。您只需根据需要为每个配方添加尽可能多的成分(并让查询完成工作)。

一个查询,例如:-

SELECT *, valor * receitas_materia_qtd AS cost 

从 receitas 加入 receitas_materia ON receitas_materia.titulo_map = receitas.titulo 加入 materia_prima ON materia_prima.codigo = receitas_materia.materia_map;

可用于列出产品及其成分,包括每种成分的成本,例如使用上面的结果是:-

例如面包使用 200 克糖,每克成本为 0.54,因此面包的糖成本为 108。

您似乎想要每件商品的总成本,因此查询如下:-

SELECT titulo, group_concat(produto||' ('||receitas_materia_qtd||' '||tipo||')') AS materias, sum(valor * receitas_materia_qtd) AS total_cost 
FROM receitas JOIN receitas_materia ON receitas_materia.titulo_map = receitas.titulo JOIN materia_prima ON materia_prima.codigo = receitas_materia.materia_map
GROUP BY titulo;

可以使用,结果是:-

基于 Android 的示例

以下是一个基本示例,它允许通过微调器将成分添加到配方中。还列出了当前成分,允许通过长按该成分来删除该成分。

该示例使用了更易于使用的光标适配器。

首先是MyDatabase,它使用建议的设计并包含各种方法:-

public class MyDatabase extends SQLiteOpenHelper 

    private static final String DATABASE_NAME = "BancoDoceDaisy.db";
    private static final int DATABASE_VERSION = 9;
    SQLiteDatabase db;

    public static final String TABLE_PRODUTO = "materia_prima";
    public static final String COLUMN_PRODUTO_CODIGO = BaseColumns._ID; /*CHANGED Use the standard Android ID column name */
    public static final String COLUMN_PRODUTO = "produto";
    public static final String COLUMN_VALOR = "valor";
    public static final String COLUMN_QTD = "quantidade";
    public static final String COLUMN_TIPO = "tipo";

    public static final String TABLE_RECEITA = "receitas";
    public static final String COLUMN_RECEITA_CODIGO = BaseColumns._ID;
    public static final String COLUMN_TITULO = "titulo";

    public static final String TABLE_RECEITA_MATERIA_MAP = TABLE_RECEITA + "_" + TABLE_PRODUTO + "_map";
    public static final String COLUMN_RECEITA_MAP = TABLE_RECEITA + "_map";
    public static final String COLUMN_PRODUTO_MAP = TABLE_PRODUTO + "_map";
    public static final String COLUMN_RECEITA_QTD = TABLE_RECEITA + "_" + COLUMN_QTD;
    public static final String DERIVED_COLUMN_COST = "cost";
    private static final String cost_calculate = TABLE_PRODUTO + "." + COLUMN_VALOR + " * " + TABLE_RECEITA_MATERIA_MAP + "." + COLUMN_RECEITA_QTD + " AS " + DERIVED_COLUMN_COST;
    public static final String DERIVED_COLUMN_TOTAL_COST = "total_cost";
    private static final String total_cost_calculate = "SUM(" +  TABLE_PRODUTO + "." + COLUMN_VALOR + " * " + TABLE_RECEITA_MATERIA_MAP + "." + COLUMN_QTD + ") AS " + DERIVED_COLUMN_TOTAL_COST;
    private final String join_receitamateria_map =
            " JOIN " + TABLE_RECEITA_MATERIA_MAP +
                    " ON " + TABLE_RECEITA + "." + COLUMN_RECEITA_CODIGO +
                    " = " + TABLE_RECEITA_MATERIA_MAP + "." + COLUMN_RECEITA_MAP;
    private final String join_produto =
            " JOIN " + TABLE_PRODUTO +
                    " ON " + TABLE_RECEITA_MATERIA_MAP + "." + COLUMN_PRODUTO_MAP +
                    " = " + TABLE_PRODUTO + "." + COLUMN_PRODUTO_CODIGO;

    private static final String fkey_options = " ON DELETE CASCADE ON UPDATE CASCADE ";

    private static volatile MyDatabase instance = null;

    private MyDatabase(@Nullable Context context) 
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        db = this.getWritableDatabase();
    

    public static MyDatabase getDatabaseInstance(Context context) 
        if (instance == null) 
            instance = new MyDatabase(context);
        
        return instance;
    

    @Override
    public void onCreate(SQLiteDatabase db) 

        String query = "CREATE TABLE "+ TABLE_PRODUTO +
                " (" + COLUMN_PRODUTO_CODIGO + " INTEGER PRIMARY KEY, " +
                COLUMN_PRODUTO + " TEXT, " +
                COLUMN_VALOR + " FLOAT, " +
                COLUMN_QTD + " FLOAT, " +
                COLUMN_TIPO + " TEXT); ";
        db.execSQL(query);
        query = "CREATE TABLE IF NOT EXISTS " + TABLE_RECEITA + "(" +
                COLUMN_RECEITA_CODIGO + " INTEGER PRIMARY KEY ," +  /* ADDED to make things simpler android wise */
                COLUMN_TITULO + " TEXT UNIQUE" +
                ")";
        db.execSQL(query);
        query = "CREATE TABLE IF NOT EXISTS "  +TABLE_RECEITA_MATERIA_MAP + "(" +
                COLUMN_RECEITA_MAP + " INTEGER REFERENCES " + TABLE_RECEITA + "(" + COLUMN_PRODUTO_CODIGO + ")" + fkey_options  + "," +
                COLUMN_PRODUTO_MAP + " INTEGER REFERENCES " + TABLE_PRODUTO + "(" + COLUMN_RECEITA_CODIGO + ")" + fkey_options + "," +
                COLUMN_RECEITA_QTD + " FLOAT, " +
                "PRIMARY KEY(" + COLUMN_RECEITA_MAP + "," + COLUMN_PRODUTO_MAP + ")" +
                ")";
        db.execSQL(query);

    

    @Override
    public void onUpgrade(SQLiteDatabase db, int i, int i1) 

    

    public long insertProduto(String produto,Float valor, Float qtd, String tipo) 
        ContentValues cv = new ContentValues();
        cv.put(COLUMN_PRODUTO,produto);
        cv.put(COLUMN_VALOR,valor);
        cv.put(COLUMN_QTD,qtd);
        cv.put(COLUMN_TIPO,tipo);
        return db.insert(TABLE_PRODUTO,null,cv);
    

    public long insertReceita(String titulo) 
        ContentValues cv = new ContentValues();
        cv.put(COLUMN_TITULO,titulo);
        return db.insert(TABLE_RECEITA,null,cv);
    

    public long insertReceitaMateria(long receitaMap, long produtoMap, Float qtd) 
        ContentValues cv = new ContentValues();
        cv.put(COLUMN_RECEITA_MAP,receitaMap);
        cv.put(COLUMN_PRODUTO_MAP,produtoMap);
        cv.put(COLUMN_RECEITA_QTD,qtd);
        return db.insert(TABLE_RECEITA_MATERIA_MAP,null,cv);
    

    public int deleteMateriaFromReceita(long receita, long produtoCodigo) 
        return  db.delete(TABLE_RECEITA_MATERIA_MAP,COLUMN_RECEITA_MAP + " =? AND " + COLUMN_PRODUTO_MAP + "=?",new String[]String.valueOf(receita), String.valueOf(produtoCodigo));
    

    public Cursor getProduto() 
        return db.query(TABLE_PRODUTO,null,null,null,null,null,null);
    
    public Cursor getReceita() 
        return db.query(TABLE_RECEITA,null,null,null,null,null,null);
    
    public Cursor getReceitaProduto(Long receita) 
        return db.query(
                TABLE_RECEITA + join_receitamateria_map + join_produto,
                new String[]"*",cost_calculate,
                TABLE_RECEITA_MATERIA_MAP + "." + COLUMN_RECEITA_MAP + "=?",new String[]receita.toString(),null,null,null);
    

    public String getReceitanameByCodigo(long codigo) 
        String rv = "NOT KNOWN";
        Cursor csr =db.query(TABLE_RECEITA,new String[]COLUMN_TITULO,COLUMN_RECEITA_CODIGO + "=?",new String[]String.valueOf(codigo),null,null,null);
        if (csr.moveToFirst()) 
            rv = csr.getString(csr.getColumnIndex(COLUMN_TITULO));
        
        csr.close();
        return rv;
    


接下来是一个初始活动MainActivity(设计为只运行一次),它添加了一些材料/产品(成分)和一些空白(无成分)receitas(食谱)。之后调用 AddProduto 活动,将蛋糕配方传递给活动:-

public class MainActivity extends AppCompatActivity 

    MyDatabase db;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        db = MyDatabase.getDatabaseInstance(this);

        db.insertProduto("Plain Flour",0.54F,1F,"Grams");
        db.insertProduto("SR Flour",0.55F,1F,"Grams");
        db.insertProduto("Eggs",1.34F,1f,"Each");
        db.insertProduto("Milk",0.2F,1F,"ml");
        db.insertProduto("Sugar",0.65F,1F,"Grams");

        db.insertReceita("Bread");
        long selectedId = db.insertReceita("Cake");
        db.insertReceita("Scone");

        Intent intent = new Intent(this,AddProduto.class);
        intent.putExtra(MyDatabase.TABLE_RECEITA,selectedId);
        startActivity(intent);
    

最后是 AddProduto 活动。这有一个微调器,可以选择一种或多种成分。选择一种成分会将成分添加到配方中,然后刷新配方的成分以显示添加的成分。如果长按成分列表中的一种成分,它将从配方中删除。

请注意,仅包含非常基本的管理。例如实际上,微调器中的成分应排除配方中已有的成分。

为了演示/示例的简单/简洁,成分的数量/数量设置为 100:-

public class AddProduto extends AppCompatActivity 

    TextView receita;
    Spinner materia_add;
    ListView materia_in;
    SimpleCursorAdapter adapter_list, adapter_spinner;
    MyDatabase db;
    Cursor csr_add, csr_in;
    long current_receita;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_produto);
        db = MyDatabase.getDatabaseInstance(this);

        receita = this.findViewById(R.id.Receita);
        current_receita = this.getIntent().getLongExtra(MyDatabase.TABLE_RECEITA,0);
        receita.setText(db.getReceitanameByCodigo(current_receita));
        materia_add = this.findViewById(R.id.materia_add);
        materia_in = this.findViewById(R.id.materia_in);
        setOrRefreshSpinner();
        setOrRefreshReceitaList();

    

    // Handling the Spinner
    private void setOrRefreshSpinner() 
        csr_add = db.getProduto();
        if (adapter_spinner == null) 
            adapter_spinner = new SimpleCursorAdapter(
                    this,
                    android.R.layout.simple_list_item_2,
                    csr_add,
                    new String[]MyDatabase.COLUMN_PRODUTO, MyDatabase.COLUMN_VALOR,
                    new int[]android.R.id.text1, android.R.id.text2,0
            );
            materia_add.setAdapter(adapter_spinner);
            materia_add.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() 
                @Override
                public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) 
                    db.insertReceitaMateria(current_receita,l,100F); // Made up value for demo
                    setOrRefreshReceitaList(); // Update the List of materia in the receita
                

                @Override
                public void onNothingSelected(AdapterView<?> adapterView) 

                
            );
         else 
            adapter_spinner.swapCursor(csr_add);
        
    

    // Handling the recipe ListView
    private void setOrRefreshReceitaList() 
        csr_in = db.getReceitaProduto(current_receita);
        if (adapter_list == null) 
            adapter_list = new SimpleCursorAdapter(
                    this,
                    android.R.layout.simple_list_item_2,
                    csr_in,
                    new String[]MyDatabase.COLUMN_PRODUTO,MyDatabase.DERIVED_COLUMN_COST,
                    new int[]android.R.id.text1,android.R.id.text2,
                    0
            );
            materia_in.setAdapter(adapter_list);
            materia_in.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() 
                @Override
                public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) 
                    db.deleteMateriaFromReceita(current_receita,l);
                    setOrRefreshReceitaList();
                    return true;
                
            );
         else 
            adapter_list.swapCursor(csr_in);
        
    

    @Override
    protected void onDestroy() 
        super.onDestroy();
        csr_in.close();
        csr_add.close();
    

结果

第一次运行时会显示 AddProduto 活动(在 MainActivity 启动之后):-

请注意,尚未包含处理 Spinner 自动选择项目的事实,因此在进行任何选择之前添加了成分(请参阅Android Spinner : Avoid onItemSelected calls during initialization in regrad 以避免这种情况)。

紫色是陀螺

teal 是配方的成分列表(成分的总成本,即 100 * 成分成本)。

从微调器中选择鸡蛋:-

然后在选择之后(添加鸡蛋):-

配料表中的LongClick普通面粉:-

【讨论】:

我不明白您在新地图表上的 PRIMARY KEY 声明:PRIMARY KEY(titulo_map,materia_map)); ??? / 我也想通过不手动添加的方法来添加数据。 @MarthaAndrade 它是一个复合主键,也就是由多个列组成的键,配方/成分组合是唯一的,例如你不能有一个食谱,比如有面粉和面粉的面包。方法很简单介绍,基本上它们只是调用 SQL。如果时间允许,我可能会提供更多基于 android 的示例。 @MarthaAndrade 添加了一个基本的工作示例应用程序,其中包括通过微调器向食谱添加成分(以及通过长按列出的成分来删除成分)。 感谢您的帮助,但仍然无法正常工作

以上是关于提要表 2 和表 1 数据 SQLite Android Studio的主要内容,如果未能解决你的问题,请参考以下文章

Android中SQLite的使用

SQLite

在java中,我怎样才能删除一个sqlite表?

提高sqlmap爆破效率

Mysql入门到入魔——2. 操纵数据库和表

支付SDK中经常用到的Sqlite数据库