복붙노트

[RUBY-ON-RAILS] 동적 레일에 바인딩 원시 업데이트 SQL을 실행하는 방법

RUBY-ON-RAILS

동적 레일에 바인딩 원시 업데이트 SQL을 실행하는 방법

나는 다음과 같은 하나의 업데이트 원시 SQL을 실행하려면 :

update table set f1=? where f2=? and f3=?

이 SQL은 액티브 :: Base.connection.execute에 의해 실행됩니다,하지만 난 방법으로 동적 매개 변수 값을 전달하는 방법을 모르겠어요.

누군가가 나에게 그것은에 어떤 도움을 줄 수 있을까?

해결법

  1. ==============================

    1.그것은 일반적으로이 작업을 수행 할 레일 API 노출하는 방법처럼 보이지 않는다. 당신은, 예를 들어, 기본 연결에 액세스하고 그것의 방법을 사용하여 시도 할 수 MySQL 용 :

    그것은 일반적으로이 작업을 수행 할 레일 API 노출하는 방법처럼 보이지 않는다. 당신은, 예를 들어, 기본 연결에 액세스하고 그것의 방법을 사용하여 시도 할 수 MySQL 용 :

    st = ActiveRecord::Base.connection.raw_connection.prepare("update table set f1=? where f2=? and f3=?")
    st.execute(f1, f2, f3)
    st.close
    

    나는 반드시이 일을 다른 파급 효과 (연결이 열려는 등)이있는 경우 아니에요. 나는 그것이 실제 쿼리를 제외하고 무엇을하고 있는지 확인하기 위해 정상적인 업데이트를 레일즈에게 코드를 추적한다.

    당신이 행이 백만 번을하는 경우가 아니라면 준비된 쿼리를 사용하여 당신에게 데이터베이스에서 시간의 작은 금액을 절약 할 수 있지만, 당신은 아마 더 나은 오프 단지 일반 루비 대체, 예를 들어,와 업데이트를 구축하는 것

    ActiveRecord::Base.connection.execute("update table set f1=#{ActiveRecord::Base.sanitize(f1)}")
    

    덧글 말한 것처럼 또는 액티브를 사용하여.

  2. ==============================

    2.액티브 :: Base.connection 문자열 값 (및 선택적으로 열 객체)를 얻어 견적 방법이있다. 당신은 이런 말을 할 수 있습니다 :

    액티브 :: Base.connection 문자열 값 (및 선택적으로 열 객체)를 얻어 견적 방법이있다. 당신은 이런 말을 할 수 있습니다 :

    ActiveRecord::Base.connection.execute(<<-EOQ)
      UPDATE  foo
      SET     bar = #{ActiveRecord::Base.connection.quote(baz)}
    EOQ
    

    참고 당신은 레일 마이그레이션 또는 해당 단축 할 수있는 액티브 객체 인 경우 :

    connection.execute(<<-EOQ)
      UPDATE  foo
      SET     bar = #{connection.quote(baz)}
    EOQ
    

    UPDATE : 점을 @kolen으로 대신 exec_update 사용해야합니다. 이것은 당신을 위해 인용을 처리하고 또한 메모리가 누수 방지 할 수 있습니다. 서명은 다른 생각을 조금 작동합니다 :

    connection.exec_update(<<-EOQ, "SQL", [[nil, baz]])
      UPDATE  foo
      SET     bar = $1
    EOQ
    

    여기서 마지막 PARAM 바인드 파라미터들을 나타내는 튜플들의 배열이다. 각 투플에서, 첫 번째 엔트리는 컬럼 유형이고, 두 번째는 값이다. 당신은 열 유형 전무을 줄 수 있으며, 레일은 일반적으로 비록 옳은 일을 할 것입니다.

    exec_query, exec_insert 및 exec_delete는 당신이 필요에 따라,도있다.

  3. ==============================

    3.당신은 같은 것을 사용한다 :

    당신은 같은 것을 사용한다 :

    YourModel.update_all(
      ActiveRecord::Base.send(:sanitize_sql_for_assignment, {:value => "'wow'"})
    )
    

    즉, 트릭을 할 것입니다. 루비 (적어도 1.8.7 버전)는 sanitize_sql_for_assignment 실제로 보호 방법이라는 사실을 건너 뛰 sanitize_sql_for_assignment를 호출 액티브 :: 자료 #의 전송 방법을하게 사용.

  4. ==============================

    4.언젠가 부모 클래스 테이블의 이름 대신보다 효율적으로 사용하는 이름이 될 것입니다 :

    언젠가 부모 클래스 테이블의 이름 대신보다 효율적으로 사용하는 이름이 될 것입니다 :

    # Refers to the current class
    self.class.unscoped.where(self.class.primary_key => id).update_all(created _at: timestamp)
    

    예를 들어, "사람"기본 클래스, 서브 클래스 (데이터베이스 테이블) "클라이언트"와 "판매자" 대신 사용 :

    Client.where(self.class.primary_key => id).update_all(created _at: timestamp)
    Seller.where(self.class.primary_key => id).update_all(created _at: timestamp)
    

    이 방법으로 기본 클래스의 객체를 사용할 수 있습니다 :

    person.class.unscoped.where(self.class.primary_key => id).update_all(created _at: timestamp)
    
  5. ==============================

    5.왜이 원시 SQL을 사용합니까?

    왜이 원시 SQL을 사용합니까?

    당신이 모델이 있다면 그것은 어디에 사용을 위해 :

    f1 = 'foo'
    f2 = 'bar'
    f3 = 'buzz'
    YourModel.where('f1 = ? and f2 = ?', f1, f2).each do |ym|
      # or where(f1: f1, f2: f2).each do (...)
      ym.update(f3: f3) 
    end
    
    

    당신이 그것을위한 모델 (단지 테이블)이없는 경우에는 액티브에서 상속 파일 및 모델을 만들 수 있습니다 :: 자료를

    class YourTable < ActiveRecord::Base
      self.table_name = 'your_table' # specify explicitly if needed
    end
    

    다시 상기와 위치를 동일하게 사용

  6. ==============================

    6.나는 액티브 2.3.8과 기능에 composite_primary_keys을 얻기에 실패했기 때문에 원시 SQL을 사용하는 데 필요한. 그래서 복합 기본 키와 SQLSERVER 2000 테이블에 액세스하기 위해 원시 SQL이 필요했다.

    나는 액티브 2.3.8과 기능에 composite_primary_keys을 얻기에 실패했기 때문에 원시 SQL을 사용하는 데 필요한. 그래서 복합 기본 키와 SQLSERVER 2000 테이블에 액세스하기 위해 원시 SQL이 필요했다.

    sql = "update [db].[dbo].[#{Contacts.table_name}] " +
          "set [COLUMN] = 0 " +
          "where [CLIENT_ID] = '#{contact.CLIENT_ID}' and CONTACT_ID = '#{contact.CONTACT_ID}'"
    st = ActiveRecord::Base.connection.raw_connection.prepare(sql)
    st.execute
    

    더 나은 솔루션을 사용할 수있는 경우, 공유하시기 바랍니다.

  7. ==============================

    7.레일 3.1에서는 쿼리 인터페이스를 사용한다 :

    레일 3.1에서는 쿼리 인터페이스를 사용한다 :

    업데이트 update_all 당신이 필요로하는 작업이다.

    참조 여기 자세한 사항 : http://m.onkey.org/active-record-query-interface

  8. from https://stackoverflow.com/questions/4483049/how-to-execute-a-raw-update-sql-with-dynamic-binding-in-rails by cc-by-sa and MIT license