17

我想更新我的数据库中的兴趣字段。我的 SQL 查询如下所示

更新 Table_Name 设置 Interest = Principal * Power(( 1 + (rate / 100),year)

此查询在 MySQL 中运行良好,但不适用于 SQLite。

错误说没有找到电源功能

有谁知道如何解决这个问题,因为我必须使用查询来一次更新超过 3000 条记录。

4

8 回答 8

19

SQLite doesn't have a lot of functions available. But the good news is that is easy enough to add your own.

Here's how to do it using the C API (which also works from Objective-C code).

First write a power function:

void sqlite_power(sqlite3_context *context, int argc, sqlite3_value **argv) {
    double num = sqlite3_value_double(argv[0]); // get the first arg to the function
    double exp = sqlite3_value_double(argv[1]); // get the second arg
    double res = pow(num, exp);                 // calculate the result
    sqlite3_result_double(context, res);        // save the result
}

Then you need to register the function:

int res = sqlite3_create_function(dbRef, "POWER", 2, SQLITE_UTF8, NULL, &sqlite_power, NULL, NULL);

The 2 is the number of arguments for the function. dbRef is of course the sqlite3 * database reference.

于 2012-11-02T06:03:56.893 回答
7

You can also create an SQLite user-defined function from python. Based on the example at docs.python.org: sqlite3.Connection.create_function

Create a python function:

def sqlite_power(x,n):
    return int(x)**n
print(sqlite_power(2,3))
# 8    

Create a SQLite user-defined function based on the python function:

con = sqlite3.connect(":memory:")
con.create_function("power", 2, sqlite_power)

Use it:

cur = con.cursor()
cur.execute("select power(?,?)", (2,3))
print cur.fetchone()[0]
# 8
于 2019-03-20T15:25:37.820 回答
5

I was strugginling with this too, but if all you need is powers of 2 (or multiples, etc) there is a simpler way:

Use the shift operator, e.g

SELECT 1 << mytable.value 

SELECT 1 << (table.x + etc..)
于 2020-07-09T17:52:04.060 回答
4

https://www.cafe-encounter.net/p3244/installing-and-using-sqlite-extensions-on-macos-and-maybe-windows-linux-too

Step was to build the Math extensions library that some wonderful person named Liam Healy wrote:

Enter following command in terminal :

Step 1) Download/ Open link http://sqlite.org/contrib/download/extension-functions.c?get=25

Step 2) Go to location where extension-functions.c is downloaded. Run command "gcc -fno-common -dynamiclib extension-functions.c -o libsqlitefunctions.dylib". This will create file libsqlitefunctions.dylib at same place then you can use that in your ios application from xcode.

Now in your cocoa app you can add:

“SELECT load_extension(’libsqlitefunctions.dylib’);”

and then you have access to all kinds of glorious methods like COS, SQRT, etc! You can use them in your app like this:

//Activate database loading
sqlite3_enable_load_extension(database, 1);
sqlite3_load_extension(database,”libsqlitefunctions.dylib”,0,0);
于 2012-11-02T07:05:23.703 回答
3

If you are using SQLite NuGet package in a .NET project, you can write an extension method and bind it at runtime;

[SQLiteFunction("pow", 2, FunctionType.Scalar)]
public class SQLitePowerExtension : SQLiteFunction
{
    public override object Invoke(object[] args)
    {
        double num = (double)args[0];
        double exp = (double)args[1];

        return Math.Pow(num, exp);
    }
}

And then use it like this;

using (var conn = new SQLiteConnection("Data Source=:memory:"))
{
    conn.Open();
    conn.BindFunction(typeof(SQLitePowerExtension).GetCustomAttribute<SQLiteFunctionAttribute>(), new SQLitePowerExtension());

    var comm = new SQLiteCommand("CREATE TABLE test (num REAL, exp REAL, result REAL)", conn);
    comm.ExecuteNonQuery();

    // Populate with some data - not shown

    comm = new SQLiteCommand($"UPDATE test SET result = pow(num, exp))", conn);
    comm.ExecuteNonQuery();
}
于 2017-01-09T19:27:39.937 回答
2

This could be solved with SQL. This works for integer exponents:

Drop Table if Exists args ;
Create Table args as Select 2.5 as Base, 4 as Exponent ;

WITH RECURSIVE pow(exponent, exponent_remainder, base, result) as (
    --FIRST EXPRESSION
    SELECT exponent,exponent -1 , base,base
    FROM args
    
    union all 
    --SECOND EXPRESSION
    select Args.exponent,pow.exponent_remainder -1, pow.base,pow.result * pow.base
    from args
    join pow on args.exponent = pow.exponent
    where pow.exponent_remainder >= 0
)
select pow.result
from pow
where pow.exponent_remainder = 0;
于 2019-10-28T18:01:10.630 回答
1
于 2012-11-02T06:01:48.817 回答
1

Actually sqlite does have pow/power as a built-in mathematical function, but you need to enable it with DSQLITE_ENABLE_MATH_FUNCTIONS.

From https://www.sqlite.org/lang_mathfunc.html#pow:

The math functions shown below are part of the SQLite amalgamation source file but are only active if the amalgamation is compiled using the -DSQLITE_ENABLE_MATH_FUNCTIONS compile-time option.

于 2021-04-15T08:51:30.353 回答